diff options
77 files changed, 24690 insertions, 11 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 585db89410..d0dfbde0d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,6 +72,7 @@ set(LLVM_ALL_TARGETS CBackend CellSPU CppBackend + Hexagon Mips MBlaze MSP430 diff --git a/autoconf/config.sub b/autoconf/config.sub index da19a880e5..9942491533 100755 --- a/autoconf/config.sub +++ b/autoconf/config.sub @@ -4,7 +4,7 @@ # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011 Free Software Foundation, Inc. -timestamp='2011-08-23' +timestamp='2011-11-02' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software @@ -256,6 +256,7 @@ case $basic_machine in | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ | fido | fr30 | frv \ + | hexagon \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ @@ -367,6 +368,7 @@ case $basic_machine in | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ + | hexagon-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ diff --git a/autoconf/configure.ac b/autoconf/configure.ac index 22f41d1070..d7fc95bdc8 100644 --- a/autoconf/configure.ac +++ b/autoconf/configure.ac @@ -357,6 +357,7 @@ AC_CACHE_CHECK([target architecture],[llvm_cv_target_arch], mips-*) llvm_cv_target_arch="Mips" ;; xcore-*) llvm_cv_target_arch="XCore" ;; msp430-*) llvm_cv_target_arch="MSP430" ;; + hexagon-*) llvm_cv_target_arch="Hexagon" ;; mblaze-*) llvm_cv_target_arch="MBlaze" ;; ptx-*) llvm_cv_target_arch="PTX" ;; *) llvm_cv_target_arch="Unknown" ;; @@ -503,6 +504,7 @@ else Mips) AC_SUBST(TARGET_HAS_JIT,1) ;; XCore) AC_SUBST(TARGET_HAS_JIT,0) ;; MSP430) AC_SUBST(TARGET_HAS_JIT,0) ;; + Hexagon) AC_SUBST(TARGET_HAS_JIT,0) ;; MBlaze) AC_SUBST(TARGET_HAS_JIT,0) ;; PTX) AC_SUBST(TARGET_HAS_JIT,0) ;; *) AC_SUBST(TARGET_HAS_JIT,0) ;; @@ -615,14 +617,14 @@ dnl Allow specific targets to be specified for building (or not) TARGETS_TO_BUILD="" AC_ARG_ENABLE([targets],AS_HELP_STRING([--enable-targets], [Build specific host targets: all or target1,target2,... Valid targets are: - host, x86, x86_64, sparc, powerpc, arm, mips, spu, + host, x86, x86_64, sparc, powerpc, arm, mips, spu, hexagon, xcore, msp430, ptx, cbe, and cpp (default=all)]),, enableval=all) if test "$enableval" = host-only ; then enableval=host fi case "$enableval" in - all) TARGETS_TO_BUILD="X86 Sparc PowerPC ARM Mips CellSPU XCore MSP430 CBackend CppBackend MBlaze PTX" ;; + all) TARGETS_TO_BUILD="X86 Sparc PowerPC ARM Mips CellSPU XCore MSP430 CBackend CppBackend MBlaze PTX Hexagon" ;; *)for a_target in `echo $enableval|sed -e 's/,/ /g' ` ; do case "$a_target" in x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; @@ -636,6 +638,7 @@ case "$enableval" in msp430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;; cbe) TARGETS_TO_BUILD="CBackend $TARGETS_TO_BUILD" ;; cpp) TARGETS_TO_BUILD="CppBackend $TARGETS_TO_BUILD" ;; + hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;; mblaze) TARGETS_TO_BUILD="MBlaze $TARGETS_TO_BUILD" ;; ptx) TARGETS_TO_BUILD="PTX $TARGETS_TO_BUILD" ;; host) case "$llvm_cv_target_arch" in @@ -649,6 +652,7 @@ case "$enableval" in CellSPU|SPU) TARGETS_TO_BUILD="CellSPU $TARGETS_TO_BUILD" ;; XCore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;; MSP430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;; + Hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;; PTX) TARGETS_TO_BUILD="PTX $TARGETS_TO_BUILD" ;; *) AC_MSG_ERROR([Can not set target to build]) ;; esac ;; @@ -1419,7 +1419,7 @@ Optional Features: --enable-targets Build specific host targets: all or target1,target2,... Valid targets are: host, x86, x86_64, sparc, powerpc, arm, mips, spu, xcore, - msp430, ptx, cbe, and cpp (default=all) + hexagon, msp430, ptx, cbe, and cpp (default=all) --enable-cbe-printf-a Enable C Backend output with hex floating point via %a (default is YES) --enable-bindings Build specific language bindings: @@ -3883,6 +3883,7 @@ else mips-*) llvm_cv_target_arch="Mips" ;; xcore-*) llvm_cv_target_arch="XCore" ;; msp430-*) llvm_cv_target_arch="MSP430" ;; + hexagon-*) llvm_cv_target_arch="Hexagon" ;; mblaze-*) llvm_cv_target_arch="MBlaze" ;; ptx-*) llvm_cv_target_arch="PTX" ;; *) llvm_cv_target_arch="Unknown" ;; @@ -5103,6 +5104,8 @@ else ;; MSP430) TARGET_HAS_JIT=0 ;; + Hexagon) TARGET_HAS_JIT=0 + ;; MBlaze) TARGET_HAS_JIT=0 ;; PTX) TARGET_HAS_JIT=0 @@ -5291,7 +5294,7 @@ if test "$enableval" = host-only ; then enableval=host fi case "$enableval" in - all) TARGETS_TO_BUILD="X86 Sparc PowerPC ARM Mips CellSPU XCore MSP430 CBackend CppBackend MBlaze PTX" ;; + all) TARGETS_TO_BUILD="X86 Sparc PowerPC ARM Mips CellSPU XCore MSP430 CBackend CppBackend MBlaze PTX Hexagon" ;; *)for a_target in `echo $enableval|sed -e 's/,/ /g' ` ; do case "$a_target" in x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; @@ -5305,6 +5308,7 @@ case "$enableval" in msp430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;; cbe) TARGETS_TO_BUILD="CBackend $TARGETS_TO_BUILD" ;; cpp) TARGETS_TO_BUILD="CppBackend $TARGETS_TO_BUILD" ;; + hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;; mblaze) TARGETS_TO_BUILD="MBlaze $TARGETS_TO_BUILD" ;; ptx) TARGETS_TO_BUILD="PTX $TARGETS_TO_BUILD" ;; host) case "$llvm_cv_target_arch" in @@ -5318,6 +5322,7 @@ case "$enableval" in CellSPU|SPU) TARGETS_TO_BUILD="CellSPU $TARGETS_TO_BUILD" ;; XCore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;; MSP430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;; + Hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;; PTX) TARGETS_TO_BUILD="PTX $TARGETS_TO_BUILD" ;; *) { { echo "$as_me:$LINENO: error: Can not set target to build" >&5 echo "$as_me: error: Can not set target to build" >&2;} diff --git a/docs/CodeGenerator.html b/docs/CodeGenerator.html index 4f762dc956..f42af12720 100644 --- a/docs/CodeGenerator.html +++ b/docs/CodeGenerator.html @@ -2288,6 +2288,7 @@ is the key:</p> <th>Feature</th> <th>ARM</th> <th>CellSPU</th> + <th>Hexagon</th> <th>MBlaze</th> <th>MSP430</th> <th>Mips</th> @@ -2302,6 +2303,7 @@ is the key:</p> <td><a href="#feat_reliable">is generally reliable</a></td> <td class="yes"></td> <!-- ARM --> <td class="no"></td> <!-- CellSPU --> + <td class="yes"></td> <!-- Hexagon --> <td class="no"></td> <!-- MBlaze --> <td class="unknown"></td> <!-- MSP430 --> <td class="yes"></td> <!-- Mips --> @@ -2316,6 +2318,7 @@ is the key:</p> <td><a href="#feat_asmparser">assembly parser</a></td> <td class="no"></td> <!-- ARM --> <td class="no"></td> <!-- CellSPU --> + <td class="no"></td> <!-- Hexagon --> <td class="yes"></td> <!-- MBlaze --> <td class="no"></td> <!-- MSP430 --> <td class="no"></td> <!-- Mips --> @@ -2330,6 +2333,7 @@ is the key:</p> <td><a href="#feat_disassembler">disassembler</a></td> <td class="yes"></td> <!-- ARM --> <td class="no"></td> <!-- CellSPU --> + <td class="no"></td> <!-- Hexagon --> <td class="yes"></td> <!-- MBlaze --> <td class="no"></td> <!-- MSP430 --> <td class="no"></td> <!-- Mips --> @@ -2344,6 +2348,7 @@ is the key:</p> <td><a href="#feat_inlineasm">inline asm</a></td> <td class="yes"></td> <!-- ARM --> <td class="no"></td> <!-- CellSPU --> + <td class="yes"></td> <!-- Hexagon --> <td class="yes"></td> <!-- MBlaze --> <td class="unknown"></td> <!-- MSP430 --> <td class="no"></td> <!-- Mips --> @@ -2358,6 +2363,7 @@ is the key:</p> <td><a href="#feat_jit">jit</a></td> <td class="partial"><a href="#feat_jit_arm">*</a></td> <!-- ARM --> <td class="no"></td> <!-- CellSPU --> + <td class="no"></td> <!-- Hexagon --> <td class="no"></td> <!-- MBlaze --> <td class="unknown"></td> <!-- MSP430 --> <td class="yes"></td> <!-- Mips --> @@ -2372,6 +2378,7 @@ is the key:</p> <td><a href="#feat_objectwrite">.o file writing</a></td> <td class="no"></td> <!-- ARM --> <td class="no"></td> <!-- CellSPU --> + <td class="no"></td> <!-- Hexagon --> <td class="yes"></td> <!-- MBlaze --> <td class="no"></td> <!-- MSP430 --> <td class="no"></td> <!-- Mips --> @@ -2386,6 +2393,7 @@ is the key:</p> <td><a href="#feat_tailcall">tail calls</a></td> <td class="yes"></td> <!-- ARM --> <td class="no"></td> <!-- CellSPU --> + <td class="yes"></td> <!-- Hexagon --> <td class="no"></td> <!-- MBlaze --> <td class="unknown"></td> <!-- MSP430 --> <td class="no"></td> <!-- Mips --> diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h index 8a16018b30..4739fb5bac 100644 --- a/include/llvm/ADT/Triple.h +++ b/include/llvm/ADT/Triple.h @@ -45,6 +45,7 @@ public: arm, // ARM; arm, armv.*, xscale cellspu, // CellSPU: spu, cellspu + hexagon, // Hexagon: hexagon mips, // MIPS: mips, mipsallegrex mipsel, // MIPSEL: mipsel, mipsallegrexel, psp mips64, // MIPS64: mips64 diff --git a/include/llvm/Intrinsics.td b/include/llvm/Intrinsics.td index 7ceeb9c7d5..5f318620c6 100644 --- a/include/llvm/Intrinsics.td +++ b/include/llvm/Intrinsics.td @@ -444,3 +444,4 @@ include "llvm/IntrinsicsARM.td" include "llvm/IntrinsicsCellSPU.td" include "llvm/IntrinsicsXCore.td" include "llvm/IntrinsicsPTX.td" +include "llvm/IntrinsicsHexagon.td" diff --git a/include/llvm/IntrinsicsHexagon.td b/include/llvm/IntrinsicsHexagon.td new file mode 100644 index 0000000000..eb5dc8fb1e --- /dev/null +++ b/include/llvm/IntrinsicsHexagon.td @@ -0,0 +1,3671 @@ +//===- IntrinsicsHexagon.td - Defines Hexagon intrinsics ---*- tablegen -*-===// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the Hexagon-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Definitions for all Hexagon intrinsics. +// +// All Hexagon intrinsics start with "llvm.hexagon.". +let TargetPrefix = "hexagon" in { + /// Hexagon_Intrinsic - Base class for all altivec intrinsics. + class Hexagon_Intrinsic<string GCCIntSuffix, list<LLVMType> ret_types, + list<LLVMType> param_types, + list<IntrinsicProperty> properties> + : GCCBuiltin<!strconcat("__builtin_", GCCIntSuffix)>, + Intrinsic<ret_types, param_types, properties>; +} + +//===----------------------------------------------------------------------===// +// +// DEF_FUNCTION_TYPE_1(QI_ftype_MEM,BT_BOOL,BT_PTR) -> +// Hexagon_qi_mem_Intrinsic<string GCCIntSuffix> +// +class Hexagon_qi_mem_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i1_ty], [llvm_ptr_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_1(void_ftype_SI,BT_VOID,BT_INT) -> +// Hexagon_void_si_Intrinsic<string GCCIntSuffix> +// +class Hexagon_void_si_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_void_ty], [llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_1(HI_ftype_SI,BT_I16,BT_INT) -> +// Hexagon_hi_si_Intrinsic<string GCCIntSuffix> +// +class Hexagon_hi_si_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i16_ty], [llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_1(SI_ftype_SI,BT_INT,BT_INT) -> +// Hexagon_si_si_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_si_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_1(DI_ftype_SI,BT_LONGLONG,BT_INT) -> +// Hexagon_di_si_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_si_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_1(SI_ftype_DI,BT_INT,BT_LONGLONG) -> +// Hexagon_si_di_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_di_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i64_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_1(DI_ftype_DI,BT_LONGLONG,BT_LONGLONG) -> +// Hexagon_di_di_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_di_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i64_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_1(QI_ftype_QI,BT_BOOL,BT_BOOL) -> +// Hexagon_qi_qi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_qi_qi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i1_ty], [llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_1(QI_ftype_SI,BT_BOOL,BT_INT) -> +// Hexagon_qi_si_Intrinsic<string GCCIntSuffix> +// +class Hexagon_qi_si_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i1_ty], [llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_1(DI_ftype_QI,BT_LONGLONG,BT_BOOL) -> +// Hexagon_di_qi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_qi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_1(SI_ftype_QI,BT_INT,BT_BOOL) -> +// Hexagon_si_qi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_qi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(QI_ftype_SISI,BT_BOOL,BT_INT,BT_INT) -> +// Hexagon_qi_sisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_qi_sisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i1_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(void_ftype_SISI,BT_VOID,BT_INT,BT_INT) -> +// Hexagon_void_sisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_void_sisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_void_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(SI_ftype_SISI,BT_INT,BT_INT,BT_INT) -> +// Hexagon_si_sisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_sisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(USI_ftype_SISI,BT_UINT,BT_INT,BT_INT) -> +// Hexagon_usi_sisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_usi_sisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(DI_ftype_SISI,BT_LONGLONG,BT_INT,BT_INT) -> +// Hexagon_di_sisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_sisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(UDI_ftype_SISI,BT_ULONGLONG,BT_INT,BT_INT) -> +// Hexagon_udi_sisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_udi_sisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(DI_ftype_SIDI,BT_LONGLONG,BT_INT,BT_LONGLONG) -> +// Hexagon_di_sidi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_sidi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i32_ty, llvm_i64_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(DI_ftype_DISI,BT_LONGLONG,BT_LONGLONG,BT_INT) -> +// Hexagon_di_disi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_disi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(SI_ftype_SIDI,BT_INT,BT_INT,BT_LONGLONG) -> +// Hexagon_si_sidi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_sidi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i32_ty, llvm_i64_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(SI_ftype_DIDI,BT_INT,BT_LONGLONG,BT_LONGLONG) -> +// Hexagon_si_didi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_didi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i64_ty, llvm_i64_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(DI_ftype_DIDI,BT_LONGLONG,BT_LONGLONG,BT_LONGLONG) -> +// Hexagon_di_didi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_didi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(UDI_ftype_DIDI,BT_ULONGLONG,BT_LONGLONG,BT_LONGLONG) -> +// Hexagon_udi_didi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_udi_didi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(SI_ftype_DISI,BT_INT,BT_LONGLONG,BT_INT) -> +// Hexagon_si_disi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_disi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i64_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(QI_ftype_DIDI,BT_BOOL,BT_LONGLONG,BT_LONGLONG) -> +// Hexagon_qi_didi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_qi_didi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i1_ty], [llvm_i64_ty, llvm_i64_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(QI_ftype_QIQI,BT_BOOL,BT_BOOL,BT_BOOL) -> +// Hexagon_qi_qiqi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_qi_qiqi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i1_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(QI_ftype_QIQIQI,BT_BOOL,BT_BOOL,BT_BOOL) -> +// Hexagon_qi_qiqiqi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_qi_qiqiqi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i1_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(SI_ftype_QIQI,BT_INT,BT_BOOL,BT_BOOL) -> +// Hexagon_si_qiqi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_qiqi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_2(SI_ftype_QISI,BT_INT,BT_BOOL,BT_INT) -> +// Hexagon_si_qisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_qisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i1_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_3(void_ftype_SISISI,BT_VOID,BT_INT,BT_INT,BT_INT) -> +// Hexagon_void_sisisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_void_sisisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_void_ty], [llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_3(SI_ftype_SISISI,BT_INT,BT_INT,BT_INT,BT_INT) -> +// Hexagon_si_sisisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_sisisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_3(DI_ftype_SISISI,BT_LONGLONG,BT_INT,BT_INT,BT_INT) -> +// Hexagon_di_sisisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_sisisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_3(SI_ftype_DISISI,BT_INT,BT_LONGLONG,BT_INT,BT_INT) -> +// Hexagon_si_disisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_disisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i64_ty, llvm_i32_ty, + llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_3(DI_ftype_DISISI,BT_LONGLONG,BT_LONGLONG,BT_INT,BT_INT) -> +// Hexagon_di_disisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_disisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty, + llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_3(SI_ftype_SIDISI,BT_INT,BT_INT,BT_LONGLONG,BT_INT) -> +// Hexagon_si_sidisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_sidisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i32_ty, llvm_i64_ty, + llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_3(DI_ftype_DIDISI,BT_LONGLONG,BT_LONGLONG, +// BT_LONGLONG,BT_INT) -> +// Hexagon_di_didisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_didisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty, + llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_3(SI_ftype_SIDIDI,BT_INT,BT_INT,BT_LONGLONG,BT_LONGLONG) -> +// Hexagon_si_sididi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_sididi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i32_ty, llvm_i64_ty, + llvm_i64_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_3(DI_ftype_DIDIDI,BT_LONGLONG,BT_LONGLONG,BT_LONGLONG, +// BT_LONGLONG) -> +// Hexagon_di_dididi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_dididi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty, + llvm_i64_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_3(SI_ftype_SISIDI,BT_INT,BT_INT,BT_INT,BT_LONGLONG) -> +// Hexagon_si_sisidi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_sisidi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, + llvm_i64_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_3(SI_ftype_QISISI,BT_INT,BT_BOOL,BT_INT,BT_INT) -> +// Hexagon_si_qisisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_qisisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_3(DI_ftype_QISISI,BT_LONGLONG,BT_BOOL,BT_INT,BT_INT) -> +// Hexagon_di_qisisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_qisisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i1_ty, llvm_i32_ty, + llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_3(DI_ftype_QIDIDI,BT_LONGLONG,BT_BOOL,BT_LONGLONG, +// BT_LONGLONG) -> +// Hexagon_di_qididi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_qididi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i32_ty, llvm_i64_ty, + llvm_i64_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_3(DI_ftype_DIDIQI,BT_LONGLONG,BT_LONGLONG,BT_LONGLONG, +// BT_BOOL) -> +// Hexagon_di_didiqi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_didiqi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty, + llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_4(SI_ftype_SISISISI,BT_INT,BT_INT,BT_INT,BT_INT,BT_INT) -> +// Hexagon_si_sisisisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_si_sisisisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +// +// DEF_FUNCTION_TYPE_4(DI_ftype_DIDISISI,BT_LONGLONG,BT_LONGLONG, +// BT_LONGLONG,BT_INT,BT_INT) -> +// Hexagon_di_didisisi_Intrinsic<string GCCIntSuffix> +// +class Hexagon_di_didisisi_Intrinsic<string GCCIntSuffix> + : Hexagon_Intrinsic<GCCIntSuffix, + [llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty, + llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + +// +// BUILTIN_INFO(HEXAGON.C2_cmpeq,QI_ftype_SISI,2) +// +def int_hexagon_C2_cmpeq : Hexagon_qi_sisi_Intrinsic<"HEXAGON.C2.cmpeq">; +// +// BUILTIN_INFO(HEXAGON.C2_cmpgt,QI_ftype_SISI,2) +// +def int_hexagon_C2_cmpgt : Hexagon_qi_sisi_Intrinsic<"HEXAGON.C2.cmpgt">; +// +// BUILTIN_INFO(HEXAGON.C2_cmpgtu,QI_ftype_SISI,2) +// +def int_hexagon_C2_cmpgtu : Hexagon_qi_sisi_Intrinsic<"HEXAGON.C2.cmpgtu">; +// +// BUILTIN_INFO(HEXAGON.C2_cmpeqp,QI_ftype_DIDI,2) +// +def int_hexagon_C2_cmpeqp : Hexagon_qi_didi_Intrinsic<"HEXAGON.C2.cmpeqp">; +// +// BUILTIN_INFO(HEXAGON.C2_cmpgtp,QI_ftype_DIDI,2) +// +def int_hexagon_C2_cmpgtp : Hexagon_qi_didi_Intrinsic<"HEXAGON.C2.cmpgtp">; +// +// BUILTIN_INFO(HEXAGON.C2_cmpgtup,QI_ftype_DIDI,2) +// +def int_hexagon_C2_cmpgtup : Hexagon_qi_didi_Intrinsic<"HEXAGON.C2.cmpgtup">; +// +// BUILTIN_INFO(HEXAGON.C2_bitsset,QI_ftype_SISI,2) +// +def int_hexagon_C2_bitsset : Hexagon_qi_sisi_Intrinsic<"HEXAGON.C2.bitsset">; +// +// BUILTIN_INFO(HEXAGON.C2_bitsclr,QI_ftype_SISI,2) +// +def int_hexagon_C2_bitsclr : Hexagon_qi_sisi_Intrinsic<"HEXAGON.C2.bitsclr">; +// +// BUILTIN_INFO(HEXAGON.C2_cmpeqi,QI_ftype_SISI,2) +// +def int_hexagon_C2_cmpeqi : Hexagon_qi_sisi_Intrinsic<"HEXAGON.C2.cmpeqi">; +// +// BUILTIN_INFO(HEXAGON.C2_cmpgti,QI_ftype_SISI,2) +// +def int_hexagon_C2_cmpgti : Hexagon_qi_sisi_Intrinsic<"HEXAGON.C2.cmpgti">; +// +// BUILTIN_INFO(HEXAGON.C2_cmpgtui,QI_ftype_SISI,2) +// +def int_hexagon_C2_cmpgtui : Hexagon_qi_sisi_Intrinsic<"HEXAGON.C2.cmpgtui">; +// +// BUILTIN_INFO(HEXAGON.C2_cmpgei,QI_ftype_SISI,2) +// +def int_hexagon_C2_cmpgei : Hexagon_qi_sisi_Intrinsic<"HEXAGON.C2.cmpgei">; +// +// BUILTIN_INFO(HEXAGON.C2_cmpgeui,QI_ftype_SISI,2) +// +def int_hexagon_C2_cmpgeui : Hexagon_qi_sisi_Intrinsic<"HEXAGON.C2.cmpgeui">; +// +// BUILTIN_INFO(HEXAGON.C2_cmplt,QI_ftype_SISI,2) +// +def int_hexagon_C2_cmplt : Hexagon_qi_sisi_Intrinsic<"HEXAGON.C2.cmplt">; +// +// BUILTIN_INFO(HEXAGON.C2_cmpltu,QI_ftype_SISI,2) +// +def int_hexagon_C2_cmpltu : Hexagon_qi_sisi_Intrinsic<"HEXAGON.C2.cmpltu">; +// +// BUILTIN_INFO(HEXAGON.C2_bitsclri,QI_ftype_SISI,2) +// +def int_hexagon_C2_bitsclri : Hexagon_qi_sisi_Intrinsic<"HEXAGON.C2.bitsclri">; +// +// BUILTIN_INFO(HEXAGON.C2_and,QI_ftype_QIQI,2) +// +def int_hexagon_C2_and : Hexagon_qi_qiqi_Intrinsic<"HEXAGON.C2.and">; +// +// BUILTIN_INFO(HEXAGON.C2_or,QI_ftype_QIQI,2) +// +def int_hexagon_C2_or : Hexagon_qi_qiqi_Intrinsic<"HEXAGON.C2.or">; +// +// BUILTIN_INFO(HEXAGON.C2_xor,QI_ftype_QIQI,2) +// +def int_hexagon_C2_xor : Hexagon_qi_qiqi_Intrinsic<"HEXAGON.C2.xor">; +// +// BUILTIN_INFO(HEXAGON.C2_andn,QI_ftype_QIQI,2) +// +def int_hexagon_C2_andn : Hexagon_qi_qiqi_Intrinsic<"HEXAGON.C2.andn">; +// +// BUILTIN_INFO(HEXAGON.C2_not,QI_ftype_QI,1) +// +def int_hexagon_C2_not : Hexagon_qi_qi_Intrinsic<"HEXAGON.C2.not">; +// +// BUILTIN_INFO(HEXAGON.C2_orn,QI_ftype_QIQI,2) +// +def int_hexagon_C2_orn : Hexagon_qi_qiqi_Intrinsic<"HEXAGON.C2.orn">; +// +// BUILTIN_INFO(HEXAGON.C2_pxfer_map,QI_ftype_QI,1) +// +def int_hexagon_C2_pxfer_map : Hexagon_qi_qi_Intrinsic<"HEXAGON.C2.pxfer.map">; +// +// BUILTIN_INFO(HEXAGON.C2_any8,QI_ftype_QI,1) +// +def int_hexagon_C2_any8 : Hexagon_qi_qi_Intrinsic<"HEXAGON.C2.any8">; +// +// BUILTIN_INFO(HEXAGON.C2_all8,QI_ftype_QI,1) +// +def int_hexagon_C2_all8 : Hexagon_qi_qi_Intrinsic<"HEXAGON.C2.all8">; +// +// BUILTIN_INFO(HEXAGON.C2_vitpack,SI_ftype_QIQI,2) +// +def int_hexagon_C2_vitpack : Hexagon_si_qiqi_Intrinsic<"HEXAGON.C2.vitpack">; +// +// BUILTIN_INFO(HEXAGON.C2_mux,SI_ftype_QISISI,3) +// +def int_hexagon_C2_mux : Hexagon_si_qisisi_Intrinsic<"HEXAGON.C2.mux">; +// +// BUILTIN_INFO(HEXAGON.C2_muxii,SI_ftype_QISISI,3) +// +def int_hexagon_C2_muxii : Hexagon_si_qisisi_Intrinsic<"HEXAGON.C2.muxii">; +// +// BUILTIN_INFO(HEXAGON.C2_muxir,SI_ftype_QISISI,3) +// +def int_hexagon_C2_muxir : Hexagon_si_qisisi_Intrinsic<"HEXAGON.C2.muxir">; +// +// BUILTIN_INFO(HEXAGON.C2_muxri,SI_ftype_QISISI,3) +// +def int_hexagon_C2_muxri : Hexagon_si_qisisi_Intrinsic<"HEXAGON.C2.muxri">; +// +// BUILTIN_INFO(HEXAGON.C2_vmux,DI_ftype_QIDIDI,3) +// +def int_hexagon_C2_vmux : Hexagon_di_qididi_Intrinsic<"HEXAGON.C2.vmux">; +// +// BUILTIN_INFO(HEXAGON.C2_mask,DI_ftype_QI,1) +// +def int_hexagon_C2_mask : Hexagon_di_qi_Intrinsic<"HEXAGON.C2.mask">; +// +// BUILTIN_INFO(HEXAGON.A2_vcmpbeq,QI_ftype_DIDI,2) +// +def int_hexagon_A2_vcmpbeq : Hexagon_qi_didi_Intrinsic<"HEXAGON.A2.vcmpbeq">; +// +// BUILTIN_INFO(HEXAGON.A2_vcmpbgtu,QI_ftype_DIDI,2) +// +def int_hexagon_A2_vcmpbgtu : Hexagon_qi_didi_Intrinsic<"HEXAGON.A2.vcmpbgtu">; +// +// BUILTIN_INFO(HEXAGON.A2_vcmpheq,QI_ftype_DIDI,2) +// +def int_hexagon_A2_vcmpheq : Hexagon_qi_didi_Intrinsic<"HEXAGON.A2.vcmpheq">; +// +// BUILTIN_INFO(HEXAGON.A2_vcmphgt,QI_ftype_DIDI,2) +// +def int_hexagon_A2_vcmphgt : Hexagon_qi_didi_Intrinsic<"HEXAGON.A2.vcmphgt">; +// +// BUILTIN_INFO(HEXAGON.A2_vcmphgtu,QI_ftype_DIDI,2) +// +def int_hexagon_A2_vcmphgtu : Hexagon_qi_didi_Intrinsic<"HEXAGON.A2.vcmphgtu">; +// +// BUILTIN_INFO(HEXAGON.A2_vcmpweq,QI_ftype_DIDI,2) +// +def int_hexagon_A2_vcmpweq : Hexagon_qi_didi_Intrinsic<"HEXAGON.A2.vcmpweq">; +// +// BUILTIN_INFO(HEXAGON.A2_vcmpwgt,QI_ftype_DIDI,2) +// +def int_hexagon_A2_vcmpwgt : Hexagon_qi_didi_Intrinsic<"HEXAGON.A2.vcmpwgt">; +// +// BUILTIN_INFO(HEXAGON.A2_vcmpwgtu,QI_ftype_DIDI,2) +// +def int_hexagon_A2_vcmpwgtu : Hexagon_qi_didi_Intrinsic<"HEXAGON.A2.vcmpwgtu">; +// +// BUILTIN_INFO(HEXAGON.C2_tfrpr,SI_ftype_QI,1) +// +def int_hexagon_C2_tfrpr : Hexagon_si_qi_Intrinsic<"HEXAGON.C2.tfrpr">; +// +// BUILTIN_INFO(HEXAGON.C2_tfrrp,QI_ftype_SI,1) +// +def int_hexagon_C2_tfrrp : Hexagon_qi_si_Intrinsic<"HEXAGON.C2.tfrrp">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_hh_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_hh_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.acc.hh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_hh_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_hh_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.acc.hh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_hl_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_hl_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.acc.hl.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_hl_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_hl_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.acc.hl.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_lh_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_lh_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.acc.lh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_lh_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_lh_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.acc.lh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_ll_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_ll_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.acc.ll.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_ll_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_ll_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.acc.ll.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_hh_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_hh_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.nac.hh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_hh_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_hh_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.nac.hh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_hl_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_hl_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.nac.hl.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_hl_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_hl_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.nac.hl.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_lh_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_lh_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.nac.lh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_lh_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_lh_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.nac.lh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_ll_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_ll_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.nac.ll.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_ll_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_ll_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.nac.ll.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_sat_hh_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_sat_hh_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.acc.sat.hh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_sat_hh_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_sat_hh_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.acc.sat.hh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_sat_hl_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_sat_hl_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.acc.sat.hl.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_sat_hl_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_sat_hl_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.acc.sat.hl.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_sat_lh_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_sat_lh_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.acc.sat.lh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_sat_lh_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_sat_lh_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.acc.sat.lh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_sat_ll_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_sat_ll_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.acc.sat.ll.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_acc_sat_ll_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_acc_sat_ll_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.acc.sat.ll.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_sat_hh_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_sat_hh_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.nac.sat.hh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_sat_hh_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_sat_hh_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.nac.sat.hh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_sat_hl_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_sat_hl_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.nac.sat.hl.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_sat_hl_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_sat_hl_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.nac.sat.hl.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_sat_lh_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_sat_lh_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.nac.sat.lh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_sat_lh_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_sat_lh_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.nac.sat.lh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_sat_ll_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_sat_ll_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.nac.sat.ll.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_nac_sat_ll_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpy_nac_sat_ll_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpy.nac.sat.ll.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_hh_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_hh_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.hh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_hh_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_hh_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.hh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_hl_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_hl_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.hl.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_hl_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_hl_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.hl.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_lh_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_lh_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.lh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_lh_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_lh_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.lh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_ll_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_ll_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.ll.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_ll_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_ll_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.ll.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_hh_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_hh_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.sat.hh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_hh_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_hh_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.sat.hh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_hl_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_hl_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.sat.hl.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_hl_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_hl_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.sat.hl.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_lh_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_lh_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.sat.lh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_lh_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_lh_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.sat.lh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_ll_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_ll_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.sat.ll.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_ll_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_ll_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.sat.ll.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_rnd_hh_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_rnd_hh_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.rnd.hh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_rnd_hh_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_rnd_hh_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.rnd.hh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_rnd_hl_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_rnd_hl_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.rnd.hl.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_rnd_hl_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_rnd_hl_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.rnd.hl.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_rnd_lh_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_rnd_lh_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.rnd.lh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_rnd_lh_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_rnd_lh_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.rnd.lh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_rnd_ll_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_rnd_ll_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.rnd.ll.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_rnd_ll_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_rnd_ll_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.rnd.ll.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_rnd_hh_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_rnd_hh_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.sat.rnd.hh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_rnd_hh_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_rnd_hh_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.sat.rnd.hh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_rnd_hl_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_rnd_hl_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.sat.rnd.hl.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_rnd_hl_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_rnd_hl_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.sat.rnd.hl.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_rnd_lh_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_rnd_lh_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.sat.rnd.lh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_rnd_lh_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_rnd_lh_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.sat.rnd.lh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_rnd_ll_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_rnd_ll_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.sat.rnd.ll.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_sat_rnd_ll_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_sat_rnd_ll_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.sat.rnd.ll.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_acc_hh_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_acc_hh_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyd.acc.hh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_acc_hh_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_acc_hh_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyd.acc.hh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_acc_hl_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_acc_hl_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyd.acc.hl.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_acc_hl_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_acc_hl_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyd.acc.hl.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_acc_lh_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_acc_lh_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyd.acc.lh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_acc_lh_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_acc_lh_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyd.acc.lh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_acc_ll_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_acc_ll_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyd.acc.ll.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_acc_ll_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_acc_ll_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyd.acc.ll.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_nac_hh_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_nac_hh_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyd.nac.hh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_nac_hh_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_nac_hh_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyd.nac.hh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_nac_hl_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_nac_hl_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyd.nac.hl.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_nac_hl_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_nac_hl_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyd.nac.hl.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_nac_lh_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_nac_lh_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyd.nac.lh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_nac_lh_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_nac_lh_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyd.nac.lh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_nac_ll_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_nac_ll_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyd.nac.ll.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_nac_ll_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyd_nac_ll_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyd.nac.ll.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_hh_s0,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_hh_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON.M2.mpyd.hh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_hh_s1,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_hh_s1 : +Hexagon_di_sisi_Intrinsic<"HEXAGON.M2.mpyd.hh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_hl_s0,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_hl_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON.M2.mpyd.hl.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_hl_s1,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_hl_s1 : +Hexagon_di_sisi_Intrinsic<"HEXAGON.M2.mpyd.hl.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_lh_s0,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_lh_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON.M2.mpyd.lh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_lh_s1,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_lh_s1 : +Hexagon_di_sisi_Intrinsic<"HEXAGON.M2.mpyd.lh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_ll_s0,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_ll_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON.M2.mpyd.ll.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_ll_s1,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_ll_s1 : +Hexagon_di_sisi_Intrinsic<"HEXAGON.M2.mpyd.ll.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_rnd_hh_s0,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_rnd_hh_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON.M2.mpyd.rnd.hh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_rnd_hh_s1,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_rnd_hh_s1 : +Hexagon_di_sisi_Intrinsic<"HEXAGON.M2.mpyd.rnd.hh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_rnd_hl_s0,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_rnd_hl_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON.M2.mpyd.rnd.hl.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_rnd_hl_s1,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_rnd_hl_s1 : +Hexagon_di_sisi_Intrinsic<"HEXAGON.M2.mpyd.rnd.hl.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_rnd_lh_s0,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_rnd_lh_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON.M2.mpyd.rnd.lh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_rnd_lh_s1,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_rnd_lh_s1 : +Hexagon_di_sisi_Intrinsic<"HEXAGON.M2.mpyd.rnd.lh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_rnd_ll_s0,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_rnd_ll_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON.M2.mpyd.rnd.ll.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyd_rnd_ll_s1,DI_ftype_SISI,2) +// +def int_hexagon_M2_mpyd_rnd_ll_s1 : +Hexagon_di_sisi_Intrinsic<"HEXAGON.M2.mpyd.rnd.ll.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_acc_hh_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_acc_hh_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpyu.acc.hh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_acc_hh_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_acc_hh_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpyu.acc.hh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_acc_hl_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_acc_hl_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpyu.acc.hl.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_acc_hl_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_acc_hl_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpyu.acc.hl.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_acc_lh_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_acc_lh_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpyu.acc.lh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_acc_lh_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_acc_lh_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpyu.acc.lh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_acc_ll_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_acc_ll_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpyu.acc.ll.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_acc_ll_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_acc_ll_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpyu.acc.ll.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_nac_hh_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_nac_hh_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpyu.nac.hh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_nac_hh_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_nac_hh_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpyu.nac.hh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_nac_hl_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_nac_hl_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpyu.nac.hl.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_nac_hl_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_nac_hl_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpyu.nac.hl.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_nac_lh_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_nac_lh_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpyu.nac.lh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_nac_lh_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_nac_lh_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpyu.nac.lh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_nac_ll_s0,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_nac_ll_s0 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpyu.nac.ll.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_nac_ll_s1,SI_ftype_SISISI,3) +// +def int_hexagon_M2_mpyu_nac_ll_s1 : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.mpyu.nac.ll.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_hh_s0,USI_ftype_SISI,2) +// +def int_hexagon_M2_mpyu_hh_s0 : +Hexagon_usi_sisi_Intrinsic<"HEXAGON.M2.mpyu.hh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_hh_s1,USI_ftype_SISI,2) +// +def int_hexagon_M2_mpyu_hh_s1 : +Hexagon_usi_sisi_Intrinsic<"HEXAGON.M2.mpyu.hh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_hl_s0,USI_ftype_SISI,2) +// +def int_hexagon_M2_mpyu_hl_s0 : +Hexagon_usi_sisi_Intrinsic<"HEXAGON.M2.mpyu.hl.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_hl_s1,USI_ftype_SISI,2) +// +def int_hexagon_M2_mpyu_hl_s1 : +Hexagon_usi_sisi_Intrinsic<"HEXAGON.M2.mpyu.hl.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_lh_s0,USI_ftype_SISI,2) +// +def int_hexagon_M2_mpyu_lh_s0 : +Hexagon_usi_sisi_Intrinsic<"HEXAGON.M2.mpyu.lh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_lh_s1,USI_ftype_SISI,2) +// +def int_hexagon_M2_mpyu_lh_s1 : +Hexagon_usi_sisi_Intrinsic<"HEXAGON.M2.mpyu.lh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_ll_s0,USI_ftype_SISI,2) +// +def int_hexagon_M2_mpyu_ll_s0 : +Hexagon_usi_sisi_Intrinsic<"HEXAGON.M2.mpyu.ll.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_ll_s1,USI_ftype_SISI,2) +// +def int_hexagon_M2_mpyu_ll_s1 : +Hexagon_usi_sisi_Intrinsic<"HEXAGON.M2.mpyu.ll.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_acc_hh_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_acc_hh_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyud.acc.hh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_acc_hh_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_acc_hh_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyud.acc.hh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_acc_hl_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_acc_hl_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyud.acc.hl.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_acc_hl_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_acc_hl_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyud.acc.hl.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_acc_lh_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_acc_lh_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyud.acc.lh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_acc_lh_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_acc_lh_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyud.acc.lh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_acc_ll_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_acc_ll_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyud.acc.ll.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_acc_ll_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_acc_ll_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyud.acc.ll.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_nac_hh_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_nac_hh_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyud.nac.hh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_nac_hh_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_nac_hh_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyud.nac.hh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_nac_hl_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_nac_hl_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyud.nac.hl.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_nac_hl_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_nac_hl_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyud.nac.hl.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_nac_lh_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_nac_lh_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyud.nac.lh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_nac_lh_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_nac_lh_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyud.nac.lh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_nac_ll_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_nac_ll_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyud.nac.ll.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_nac_ll_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_mpyud_nac_ll_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.mpyud.nac.ll.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_hh_s0,UDI_ftype_SISI,2) +// +def int_hexagon_M2_mpyud_hh_s0 : +Hexagon_udi_sisi_Intrinsic<"HEXAGON.M2.mpyud.hh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_hh_s1,UDI_ftype_SISI,2) +// +def int_hexagon_M2_mpyud_hh_s1 : +Hexagon_udi_sisi_Intrinsic<"HEXAGON.M2.mpyud.hh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_hl_s0,UDI_ftype_SISI,2) +// +def int_hexagon_M2_mpyud_hl_s0 : +Hexagon_udi_sisi_Intrinsic<"HEXAGON.M2.mpyud.hl.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_hl_s1,UDI_ftype_SISI,2) +// +def int_hexagon_M2_mpyud_hl_s1 : +Hexagon_udi_sisi_Intrinsic<"HEXAGON.M2.mpyud.hl.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_lh_s0,UDI_ftype_SISI,2) +// +def int_hexagon_M2_mpyud_lh_s0 : +Hexagon_udi_sisi_Intrinsic<"HEXAGON.M2.mpyud.lh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_lh_s1,UDI_ftype_SISI,2) +// +def int_hexagon_M2_mpyud_lh_s1 : +Hexagon_udi_sisi_Intrinsic<"HEXAGON.M2.mpyud.lh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_ll_s0,UDI_ftype_SISI,2) +// +def int_hexagon_M2_mpyud_ll_s0 : +Hexagon_udi_sisi_Intrinsic<"HEXAGON.M2.mpyud.ll.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyud_ll_s1,UDI_ftype_SISI,2) +// +def int_hexagon_M2_mpyud_ll_s1 : +Hexagon_udi_sisi_Intrinsic<"HEXAGON.M2.mpyud.ll.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mpysmi,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpysmi : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpysmi">; +// +// BUILTIN_INFO(HEXAGON.M2_macsip,SI_ftype_SISISI,3) +// +def int_hexagon_M2_macsip : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.macsip">; +// +// BUILTIN_INFO(HEXAGON.M2_macsin,SI_ftype_SISISI,3) +// +def int_hexagon_M2_macsin : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.macsin">; +// +// BUILTIN_INFO(HEXAGON.M2_dpmpyss_s0,DI_ftype_SISI,2) +// +def int_hexagon_M2_dpmpyss_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON.M2.dpmpyss.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_dpmpyss_acc_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_dpmpyss_acc_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.dpmpyss.acc.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_dpmpyss_nac_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_dpmpyss_nac_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.dpmpyss.nac.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_dpmpyuu_s0,UDI_ftype_SISI,2) +// +def int_hexagon_M2_dpmpyuu_s0 : +Hexagon_udi_sisi_Intrinsic<"HEXAGON.M2.dpmpyuu.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_dpmpyuu_acc_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_dpmpyuu_acc_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.dpmpyuu.acc.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_dpmpyuu_nac_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_dpmpyuu_nac_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.dpmpyuu.nac.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpy_up,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpy_up : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpy.up">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyu_up,USI_ftype_SISI,2) +// +def int_hexagon_M2_mpyu_up : +Hexagon_usi_sisi_Intrinsic<"HEXAGON.M2.mpyu.up">; +// +// BUILTIN_INFO(HEXAGON.M2_dpmpyss_rnd_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_dpmpyss_rnd_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.dpmpyss.rnd.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyi,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpyi : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpyi">; +// +// BUILTIN_INFO(HEXAGON.M2_mpyui,SI_ftype_SISI,2) +// +def int_hexagon_M2_mpyui : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.mpyui">; +// +// BUILTIN_INFO(HEXAGON.M2_maci,SI_ftype_SISISI,3) +// +def int_hexagon_M2_maci : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.maci">; +// +// BUILTIN_INFO(HEXAGON.M2_acci,SI_ftype_SISISI,3) +// +def int_hexagon_M2_acci : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.acci">; +// +// BUILTIN_INFO(HEXAGON.M2_accii,SI_ftype_SISISI,3) +// +def int_hexagon_M2_accii : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.accii">; +// +// BUILTIN_INFO(HEXAGON.M2_nacci,SI_ftype_SISISI,3) +// +def int_hexagon_M2_nacci : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.nacci">; +// +// BUILTIN_INFO(HEXAGON.M2_naccii,SI_ftype_SISISI,3) +// +def int_hexagon_M2_naccii : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.naccii">; +// +// BUILTIN_INFO(HEXAGON.M2_subacc,SI_ftype_SISISI,3) +// +def int_hexagon_M2_subacc : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.subacc">; +// +// BUILTIN_INFO(HEXAGON.M2_vmpy2s_s0,DI_ftype_SISI,2) +// +def int_hexagon_M2_vmpy2s_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON.M2.vmpy2s.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vmpy2s_s1,DI_ftype_SISI,2) +// +def int_hexagon_M2_vmpy2s_s1 : +Hexagon_di_sisi_Intrinsic<"HEXAGON.M2.vmpy2s.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_vmac2s_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_vmac2s_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.vmac2s.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vmac2s_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_vmac2s_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.vmac2s.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_vmpy2s_s0pack,SI_ftype_SISI,2) +// +def int_hexagon_M2_vmpy2s_s0pack : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.vmpy2s.s0pack">; +// +// BUILTIN_INFO(HEXAGON.M2_vmpy2s_s1pack,SI_ftype_SISI,2) +// +def int_hexagon_M2_vmpy2s_s1pack : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.vmpy2s.s1pack">; +// +// BUILTIN_INFO(HEXAGON.M2_vmac2,DI_ftype_DISISI,3) +// +def int_hexagon_M2_vmac2 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.vmac2">; +// +// BUILTIN_INFO(HEXAGON.M2_vmpy2es_s0,DI_ftype_DIDI,2) +// +def int_hexagon_M2_vmpy2es_s0 : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.vmpy2es.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vmpy2es_s1,DI_ftype_DIDI,2) +// +def int_hexagon_M2_vmpy2es_s1 : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.vmpy2es.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_vmac2es_s0,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_vmac2es_s0 : +Hexagon_di_dididi_Intrinsic<"HEXAGON.M2.vmac2es.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vmac2es_s1,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_vmac2es_s1 : +Hexagon_di_dididi_Intrinsic<"HEXAGON.M2.vmac2es.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_vmac2es,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_vmac2es : +Hexagon_di_dididi_Intrinsic<"HEXAGON.M2.vmac2es">; +// +// BUILTIN_INFO(HEXAGON.M2_vrmac_s0,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_vrmac_s0 : +Hexagon_di_dididi_Intrinsic<"HEXAGON.M2.vrmac.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vrmpy_s0,DI_ftype_DIDI,2) +// +def int_hexagon_M2_vrmpy_s0 : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.vrmpy.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vdmpyrs_s0,SI_ftype_DIDI,2) +// +def int_hexagon_M2_vdmpyrs_s0 : +Hexagon_si_didi_Intrinsic<"HEXAGON.M2.vdmpyrs.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vdmpyrs_s1,SI_ftype_DIDI,2) +// +def int_hexagon_M2_vdmpyrs_s1 : +Hexagon_si_didi_Intrinsic<"HEXAGON.M2.vdmpyrs.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_vdmacs_s0,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_vdmacs_s0 : +Hexagon_di_dididi_Intrinsic<"HEXAGON.M2.vdmacs.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vdmacs_s1,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_vdmacs_s1 : +Hexagon_di_dididi_Intrinsic<"HEXAGON.M2.vdmacs.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_vdmpys_s0,DI_ftype_DIDI,2) +// +def int_hexagon_M2_vdmpys_s0 : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.vdmpys.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vdmpys_s1,DI_ftype_DIDI,2) +// +def int_hexagon_M2_vdmpys_s1 : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.vdmpys.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_cmpyrs_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_cmpyrs_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.cmpyrs.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_cmpyrs_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_cmpyrs_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.cmpyrs.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_cmpyrsc_s0,SI_ftype_SISI,2) +// +def int_hexagon_M2_cmpyrsc_s0 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.cmpyrsc.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_cmpyrsc_s1,SI_ftype_SISI,2) +// +def int_hexagon_M2_cmpyrsc_s1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.cmpyrsc.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_cmacs_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_cmacs_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.cmacs.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_cmacs_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_cmacs_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.cmacs.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_cmacsc_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_cmacsc_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.cmacsc.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_cmacsc_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_cmacsc_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.cmacsc.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_cmpys_s0,DI_ftype_SISI,2) +// +def int_hexagon_M2_cmpys_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON.M2.cmpys.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_cmpys_s1,DI_ftype_SISI,2) +// +def int_hexagon_M2_cmpys_s1 : +Hexagon_di_sisi_Intrinsic<"HEXAGON.M2.cmpys.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_cmpysc_s0,DI_ftype_SISI,2) +// +def int_hexagon_M2_cmpysc_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON.M2.cmpysc.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_cmpysc_s1,DI_ftype_SISI,2) +// +def int_hexagon_M2_cmpysc_s1 : +Hexagon_di_sisi_Intrinsic<"HEXAGON.M2.cmpysc.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_cnacs_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_cnacs_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.cnacs.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_cnacs_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_cnacs_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.cnacs.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_cnacsc_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_cnacsc_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.cnacsc.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_cnacsc_s1,DI_ftype_DISISI,3) +// +def int_hexagon_M2_cnacsc_s1 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.cnacsc.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_vrcmpys_s1,DI_ftype_DISI,2) +// +def int_hexagon_M2_vrcmpys_s1 : +Hexagon_di_disi_Intrinsic<"HEXAGON.M2.vrcmpys.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_vrcmpys_acc_s1,DI_ftype_DIDISI,3) +// +def int_hexagon_M2_vrcmpys_acc_s1 : +Hexagon_di_didisi_Intrinsic<"HEXAGON.M2.vrcmpys.acc.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_vrcmpys_s1rp,SI_ftype_DISI,2) +// +def int_hexagon_M2_vrcmpys_s1rp : +Hexagon_si_disi_Intrinsic<"HEXAGON.M2.vrcmpys.s1rp">; +// +// BUILTIN_INFO(HEXAGON.M2_mmacls_s0,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmacls_s0 : +Hexagon_di_dididi_Intrinsic<"HEXAGON.M2.mmacls.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmacls_s1,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmacls_s1 : +Hexagon_di_dididi_Intrinsic<"HEXAGON.M2.mmacls.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mmachs_s0,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmachs_s0 : +Hexagon_di_dididi_Intrinsic<"HEXAGON.M2.mmachs.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmachs_s1,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmachs_s1 : +Hexagon_di_dididi_Intrinsic<"HEXAGON.M2.mmachs.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyl_s0,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyl_s0 : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.mmpyl.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyl_s1,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyl_s1 : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.mmpyl.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyh_s0,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyh_s0 : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.mmpyh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyh_s1,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyh_s1 : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.mmpyh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mmacls_rs0,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmacls_rs0 : +Hexagon_di_dididi_Intrinsic<"HEXAGON.M2.mmacls.rs0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmacls_rs1,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmacls_rs1 : +Hexagon_di_dididi_Intrinsic<"HEXAGON.M2.mmacls.rs1">; +// +// BUILTIN_INFO(HEXAGON.M2_mmachs_rs0,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmachs_rs0 : +Hexagon_di_dididi_Intrinsic<"HEXAGON.M2.mmachs.rs0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmachs_rs1,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmachs_rs1 : +Hexagon_di_dididi_Intrinsic<"HEXAGON.M2.mmachs.rs1">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyl_rs0,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyl_rs0 : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.mmpyl.rs0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyl_rs1,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyl_rs1 : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.mmpyl.rs1">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyh_rs0,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyh_rs0 : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.mmpyh.rs0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyh_rs1,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyh_rs1 : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.mmpyh.rs1">; +// +// BUILTIN_INFO(HEXAGON.M2_hmmpyl_rs1,SI_ftype_SISI,2) +// +def int_hexagon_M2_hmmpyl_rs1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.hmmpyl.rs1">; +// +// BUILTIN_INFO(HEXAGON.M2_hmmpyh_rs1,SI_ftype_SISI,2) +// +def int_hexagon_M2_hmmpyh_rs1 : +Hexagon_si_sisi_Intrinsic<"HEXAGON.M2.hmmpyh.rs1">; +// +// BUILTIN_INFO(HEXAGON.M2_mmaculs_s0,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmaculs_s0 : +Hexagon_di_dididi_Intrinsic<"HEXAGON.M2.mmaculs.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmaculs_s1,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmaculs_s1 : +Hexagon_di_dididi_Intrinsic<"HEXAGON.M2.mmaculs.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mmacuhs_s0,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmacuhs_s0 : +Hexagon_di_dididi_Intrinsic<"HEXAGON.M2.mmacuhs.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmacuhs_s1,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmacuhs_s1 : +Hexagon_di_dididi_Intrinsic<"HEXAGON.M2.mmacuhs.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyul_s0,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyul_s0 : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.mmpyul.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyul_s1,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyul_s1 : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.mmpyul.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyuh_s0,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyuh_s0 : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.mmpyuh.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyuh_s1,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyuh_s1 : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.mmpyuh.s1">; +// +// BUILTIN_INFO(HEXAGON.M2_mmaculs_rs0,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmaculs_rs0 : +Hexagon_di_dididi_Intrinsic<"HEXAGON.M2.mmaculs.rs0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmaculs_rs1,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmaculs_rs1 : +Hexagon_di_dididi_Intrinsic<"HEXAGON.M2.mmaculs.rs1">; +// +// BUILTIN_INFO(HEXAGON.M2_mmacuhs_rs0,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmacuhs_rs0 : +Hexagon_di_dididi_Intrinsic<"HEXAGON.M2.mmacuhs.rs0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmacuhs_rs1,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_mmacuhs_rs1 : +Hexagon_di_dididi_Intrinsic<"HEXAGON.M2.mmacuhs.rs1">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyul_rs0,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyul_rs0 : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.mmpyul.rs0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyul_rs1,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyul_rs1 : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.mmpyul.rs1">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyuh_rs0,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyuh_rs0 : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.mmpyuh.rs0">; +// +// BUILTIN_INFO(HEXAGON.M2_mmpyuh_rs1,DI_ftype_DIDI,2) +// +def int_hexagon_M2_mmpyuh_rs1 : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.mmpyuh.rs1">; +// +// BUILTIN_INFO(HEXAGON.M2_vrcmaci_s0,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_vrcmaci_s0 : +Hexagon_di_dididi_Intrinsic<"HEXAGON.M2.vrcmaci.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vrcmacr_s0,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_vrcmacr_s0 : +Hexagon_di_dididi_Intrinsic<"HEXAGON.M2.vrcmacr.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vrcmaci_s0c,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_vrcmaci_s0c : +Hexagon_di_dididi_Intrinsic<"HEXAGON.M2.vrcmaci.s0c">; +// +// BUILTIN_INFO(HEXAGON.M2_vrcmacr_s0c,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_vrcmacr_s0c : +Hexagon_di_dididi_Intrinsic<"HEXAGON.M2.vrcmacr.s0c">; +// +// BUILTIN_INFO(HEXAGON.M2_cmaci_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_cmaci_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.cmaci.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_cmacr_s0,DI_ftype_DISISI,3) +// +def int_hexagon_M2_cmacr_s0 : +Hexagon_di_disisi_Intrinsic<"HEXAGON.M2.cmacr.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vrcmpyi_s0,DI_ftype_DIDI,2) +// +def int_hexagon_M2_vrcmpyi_s0 : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.vrcmpyi.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vrcmpyr_s0,DI_ftype_DIDI,2) +// +def int_hexagon_M2_vrcmpyr_s0 : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.vrcmpyr.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vrcmpyi_s0c,DI_ftype_DIDI,2) +// +def int_hexagon_M2_vrcmpyi_s0c : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.vrcmpyi.s0c">; +// +// BUILTIN_INFO(HEXAGON.M2_vrcmpyr_s0c,DI_ftype_DIDI,2) +// +def int_hexagon_M2_vrcmpyr_s0c : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.vrcmpyr.s0c">; +// +// BUILTIN_INFO(HEXAGON.M2_cmpyi_s0,DI_ftype_SISI,2) +// +def int_hexagon_M2_cmpyi_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON.M2.cmpyi.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_cmpyr_s0,DI_ftype_SISI,2) +// +def int_hexagon_M2_cmpyr_s0 : +Hexagon_di_sisi_Intrinsic<"HEXAGON.M2.cmpyr.s0">; +// +// BUILTIN_INFO(HEXAGON.M2_vcmpy_s0_sat_i,DI_ftype_DIDI,2) +// +def int_hexagon_M2_vcmpy_s0_sat_i : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.vcmpy.s0.sat.i">; +// +// BUILTIN_INFO(HEXAGON.M2_vcmpy_s0_sat_r,DI_ftype_DIDI,2) +// +def int_hexagon_M2_vcmpy_s0_sat_r : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.vcmpy.s0.sat.r">; +// +// BUILTIN_INFO(HEXAGON.M2_vcmpy_s1_sat_i,DI_ftype_DIDI,2) +// +def int_hexagon_M2_vcmpy_s1_sat_i : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.vcmpy.s1.sat.i">; +// +// BUILTIN_INFO(HEXAGON.M2_vcmpy_s1_sat_r,DI_ftype_DIDI,2) +// +def int_hexagon_M2_vcmpy_s1_sat_r : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.vcmpy.s1.sat.r">; +// +// BUILTIN_INFO(HEXAGON.M2_vcmac_s0_sat_i,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_vcmac_s0_sat_i : +Hexagon_di_dididi_Intrinsic<"HEXAGON.M2.vcmac.s0.sat.i">; +// +// BUILTIN_INFO(HEXAGON.M2_vcmac_s0_sat_r,DI_ftype_DIDIDI,3) +// +def int_hexagon_M2_vcmac_s0_sat_r : +Hexagon_di_dididi_Intrinsic<"HEXAGON.M2.vcmac.s0.sat.r">; +// +// BUILTIN_INFO(HEXAGON.S2_vcrotate,DI_ftype_DISI,2) +// +def int_hexagon_S2_vcrotate : +Hexagon_di_disi_Intrinsic<"HEXAGON.S2.vcrotate">; +// +// BUILTIN_INFO(HEXAGON.A2_add,SI_ftype_SISI,2) +// +def int_hexagon_A2_add : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.add">; +// +// BUILTIN_INFO(HEXAGON.A2_sub,SI_ftype_SISI,2) +// +def int_hexagon_A2_sub : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.sub">; +// +// BUILTIN_INFO(HEXAGON.A2_addsat,SI_ftype_SISI,2) +// +def int_hexagon_A2_addsat : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.addsat">; +// +// BUILTIN_INFO(HEXAGON.A2_subsat,SI_ftype_SISI,2) +// +def int_hexagon_A2_subsat : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.subsat">; +// +// BUILTIN_INFO(HEXAGON.A2_addi,SI_ftype_SISI,2) +// +def int_hexagon_A2_addi : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.addi">; +// +// BUILTIN_INFO(HEXAGON.A2_addh_l16_ll,SI_ftype_SISI,2) +// +def int_hexagon_A2_addh_l16_ll : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.addh.l16.ll">; +// +// BUILTIN_INFO(HEXAGON.A2_addh_l16_hl,SI_ftype_SISI,2) +// +def int_hexagon_A2_addh_l16_hl : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.addh.l16.hl">; +def int_hexagon_A2_addh_l16_lh : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.addh.l16.lh">; +def int_hexagon_A2_addh_l16_hh : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.addh.l16.hh">; +// +// BUILTIN_INFO(HEXAGON.A2_addh_l16_sat_ll,SI_ftype_SISI,2) +// +def int_hexagon_A2_addh_l16_sat_ll : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.addh.l16.sat.ll">; +// +// BUILTIN_INFO(HEXAGON.A2_addh_l16_sat_hl,SI_ftype_SISI,2) +// +def int_hexagon_A2_addh_l16_sat_hl : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.addh.l16.sat.hl">; +def int_hexagon_A2_addh_l16_sat_lh : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.addh.l16.sat.lh">; +def int_hexagon_A2_addh_l16_sat_hh : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.addh.l16.sat.hh">; +// +// BUILTIN_INFO(HEXAGON.A2_subh_l16_ll,SI_ftype_SISI,2) +// +def int_hexagon_A2_subh_l16_ll : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.subh.l16.ll">; +// +// BUILTIN_INFO(HEXAGON.A2_subh_l16_hl,SI_ftype_SISI,2) +// +def int_hexagon_A2_subh_l16_hl : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.subh.l16.hl">; +// +// BUILTIN_INFO(HEXAGON.A2_subh_l16_sat_ll,SI_ftype_SISI,2) +// +def int_hexagon_A2_subh_l16_sat_ll : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.subh.l16.sat.ll">; +// +// BUILTIN_INFO(HEXAGON.A2_subh_l16_sat_hl,SI_ftype_SISI,2) +// +def int_hexagon_A2_subh_l16_sat_hl : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.subh.l16.sat.hl">; +// +// BUILTIN_INFO(HEXAGON.A2_addh_h16_ll,SI_ftype_SISI,2) +// +def int_hexagon_A2_addh_h16_ll : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.addh.h16.ll">; +// +// BUILTIN_INFO(HEXAGON.A2_addh_h16_lh,SI_ftype_SISI,2) +// +def int_hexagon_A2_addh_h16_lh : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.addh.h16.lh">; +// +// BUILTIN_INFO(HEXAGON.A2_addh_h16_hl,SI_ftype_SISI,2) +// +def int_hexagon_A2_addh_h16_hl : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.addh.h16.hl">; +// +// BUILTIN_INFO(HEXAGON.A2_addh_h16_hh,SI_ftype_SISI,2) +// +def int_hexagon_A2_addh_h16_hh : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.addh.h16.hh">; +// +// BUILTIN_INFO(HEXAGON.A2_addh_h16_sat_ll,SI_ftype_SISI,2) +// +def int_hexagon_A2_addh_h16_sat_ll : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.addh.h16.sat.ll">; +// +// BUILTIN_INFO(HEXAGON.A2_addh_h16_sat_lh,SI_ftype_SISI,2) +// +def int_hexagon_A2_addh_h16_sat_lh : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.addh.h16.sat.lh">; +// +// BUILTIN_INFO(HEXAGON.A2_addh_h16_sat_hl,SI_ftype_SISI,2) +// +def int_hexagon_A2_addh_h16_sat_hl : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.addh.h16.sat.hl">; +// +// BUILTIN_INFO(HEXAGON.A2_addh_h16_sat_hh,SI_ftype_SISI,2) +// +def int_hexagon_A2_addh_h16_sat_hh : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.addh.h16.sat.hh">; +// +// BUILTIN_INFO(HEXAGON.A2_subh_h16_ll,SI_ftype_SISI,2) +// +def int_hexagon_A2_subh_h16_ll : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.subh.h16.ll">; +// +// BUILTIN_INFO(HEXAGON.A2_subh_h16_lh,SI_ftype_SISI,2) +// +def int_hexagon_A2_subh_h16_lh : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.subh.h16.lh">; +// +// BUILTIN_INFO(HEXAGON.A2_subh_h16_hl,SI_ftype_SISI,2) +// +def int_hexagon_A2_subh_h16_hl : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.subh.h16.hl">; +// +// BUILTIN_INFO(HEXAGON.A2_subh_h16_hh,SI_ftype_SISI,2) +// +def int_hexagon_A2_subh_h16_hh : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.subh.h16.hh">; +// +// BUILTIN_INFO(HEXAGON.A2_subh_h16_sat_ll,SI_ftype_SISI,2) +// +def int_hexagon_A2_subh_h16_sat_ll : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.subh.h16.sat.ll">; +// +// BUILTIN_INFO(HEXAGON.A2_subh_h16_sat_lh,SI_ftype_SISI,2) +// +def int_hexagon_A2_subh_h16_sat_lh : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.subh.h16.sat.lh">; +// +// BUILTIN_INFO(HEXAGON.A2_subh_h16_sat_hl,SI_ftype_SISI,2) +// +def int_hexagon_A2_subh_h16_sat_hl : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.subh.h16.sat.hl">; +// +// BUILTIN_INFO(HEXAGON.A2_subh_h16_sat_hh,SI_ftype_SISI,2) +// +def int_hexagon_A2_subh_h16_sat_hh : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.subh.h16.sat.hh">; +// +// BUILTIN_INFO(HEXAGON.A2_aslh,SI_ftype_SI,1) +// +def int_hexagon_A2_aslh : +Hexagon_si_si_Intrinsic<"HEXAGON.A2.aslh">; +// +// BUILTIN_INFO(HEXAGON.A2_asrh,SI_ftype_SI,1) +// +def int_hexagon_A2_asrh : +Hexagon_si_si_Intrinsic<"HEXAGON.A2.asrh">; +// +// BUILTIN_INFO(HEXAGON.A2_addp,DI_ftype_DIDI,2) +// +def int_hexagon_A2_addp : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.addp">; +// +// BUILTIN_INFO(HEXAGON.A2_addpsat,DI_ftype_DIDI,2) +// +def int_hexagon_A2_addpsat : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.addpsat">; +// +// BUILTIN_INFO(HEXAGON.A2_addsp,DI_ftype_SIDI,2) +// +def int_hexagon_A2_addsp : +Hexagon_di_sidi_Intrinsic<"HEXAGON.A2.addsp">; +// +// BUILTIN_INFO(HEXAGON.A2_subp,DI_ftype_DIDI,2) +// +def int_hexagon_A2_subp : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.subp">; +// +// BUILTIN_INFO(HEXAGON.A2_neg,SI_ftype_SI,1) +// +def int_hexagon_A2_neg : +Hexagon_si_si_Intrinsic<"HEXAGON.A2.neg">; +// +// BUILTIN_INFO(HEXAGON.A2_negsat,SI_ftype_SI,1) +// +def int_hexagon_A2_negsat : +Hexagon_si_si_Intrinsic<"HEXAGON.A2.negsat">; +// +// BUILTIN_INFO(HEXAGON.A2_abs,SI_ftype_SI,1) +// +def int_hexagon_A2_abs : +Hexagon_si_si_Intrinsic<"HEXAGON.A2.abs">; +// +// BUILTIN_INFO(HEXAGON.A2_abssat,SI_ftype_SI,1) +// +def int_hexagon_A2_abssat : +Hexagon_si_si_Intrinsic<"HEXAGON.A2.abssat">; +// +// BUILTIN_INFO(HEXAGON.A2_vconj,DI_ftype_DI,1) +// +def int_hexagon_A2_vconj : +Hexagon_di_di_Intrinsic<"HEXAGON.A2.vconj">; +// +// BUILTIN_INFO(HEXAGON.A2_negp,DI_ftype_DI,1) +// +def int_hexagon_A2_negp : +Hexagon_di_di_Intrinsic<"HEXAGON.A2.negp">; +// +// BUILTIN_INFO(HEXAGON.A2_absp,DI_ftype_DI,1) +// +def int_hexagon_A2_absp : +Hexagon_di_di_Intrinsic<"HEXAGON.A2.absp">; +// +// BUILTIN_INFO(HEXAGON.A2_max,SI_ftype_SISI,2) +// +def int_hexagon_A2_max : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.max">; +// +// BUILTIN_INFO(HEXAGON.A2_maxu,USI_ftype_SISI,2) +// +def int_hexagon_A2_maxu : +Hexagon_usi_sisi_Intrinsic<"HEXAGON.A2.maxu">; +// +// BUILTIN_INFO(HEXAGON.A2_min,SI_ftype_SISI,2) +// +def int_hexagon_A2_min : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.min">; +// +// BUILTIN_INFO(HEXAGON.A2_minu,USI_ftype_SISI,2) +// +def int_hexagon_A2_minu : +Hexagon_usi_sisi_Intrinsic<"HEXAGON.A2.minu">; +// +// BUILTIN_INFO(HEXAGON.A2_maxp,DI_ftype_DIDI,2) +// +def int_hexagon_A2_maxp : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.maxp">; +// +// BUILTIN_INFO(HEXAGON.A2_maxup,UDI_ftype_DIDI,2) +// +def int_hexagon_A2_maxup : +Hexagon_udi_didi_Intrinsic<"HEXAGON.A2.maxup">; +// +// BUILTIN_INFO(HEXAGON.A2_minp,DI_ftype_DIDI,2) +// +def int_hexagon_A2_minp : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.minp">; +// +// BUILTIN_INFO(HEXAGON.A2_minup,UDI_ftype_DIDI,2) +// +def int_hexagon_A2_minup : +Hexagon_udi_didi_Intrinsic<"HEXAGON.A2.minup">; +// +// BUILTIN_INFO(HEXAGON.A2_tfr,SI_ftype_SI,1) +// +def int_hexagon_A2_tfr : +Hexagon_si_si_Intrinsic<"HEXAGON.A2.tfr">; +// +// BUILTIN_INFO(HEXAGON.A2_tfrsi,SI_ftype_SI,1) +// +def int_hexagon_A2_tfrsi : +Hexagon_si_si_Intrinsic<"HEXAGON.A2.tfrsi">; +// +// BUILTIN_INFO(HEXAGON.A2_tfrp,DI_ftype_DI,1) +// +def int_hexagon_A2_tfrp : +Hexagon_di_di_Intrinsic<"HEXAGON.A2.tfrp">; +// +// BUILTIN_INFO(HEXAGON.A2_tfrpi,DI_ftype_SI,1) +// +def int_hexagon_A2_tfrpi : +Hexagon_di_si_Intrinsic<"HEXAGON.A2.tfrpi">; +// +// BUILTIN_INFO(HEXAGON.A2_zxtb,SI_ftype_SI,1) +// +def int_hexagon_A2_zxtb : +Hexagon_si_si_Intrinsic<"HEXAGON.A2.zxtb">; +// +// BUILTIN_INFO(HEXAGON.A2_sxtb,SI_ftype_SI,1) +// +def int_hexagon_A2_sxtb : +Hexagon_si_si_Intrinsic<"HEXAGON.A2.sxtb">; +// +// BUILTIN_INFO(HEXAGON.A2_zxth,SI_ftype_SI,1) +// +def int_hexagon_A2_zxth : +Hexagon_si_si_Intrinsic<"HEXAGON.A2.zxth">; +// +// BUILTIN_INFO(HEXAGON.A2_sxth,SI_ftype_SI,1) +// +def int_hexagon_A2_sxth : +Hexagon_si_si_Intrinsic<"HEXAGON.A2.sxth">; +// +// BUILTIN_INFO(HEXAGON.A2_combinew,DI_ftype_SISI,2) +// +def int_hexagon_A2_combinew : +Hexagon_di_sisi_Intrinsic<"HEXAGON.A2.combinew">; +// +// BUILTIN_INFO(HEXAGON.A2_combineii,DI_ftype_SISI,2) +// +def int_hexagon_A2_combineii : +Hexagon_di_sisi_Intrinsic<"HEXAGON.A2.combineii">; +// +// BUILTIN_INFO(HEXAGON.A2_combine_hh,SI_ftype_SISI,2) +// +def int_hexagon_A2_combine_hh : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.combine.hh">; +// +// BUILTIN_INFO(HEXAGON.A2_combine_hl,SI_ftype_SISI,2) +// +def int_hexagon_A2_combine_hl : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.combine.hl">; +// +// BUILTIN_INFO(HEXAGON.A2_combine_lh,SI_ftype_SISI,2) +// +def int_hexagon_A2_combine_lh : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.combine.lh">; +// +// BUILTIN_INFO(HEXAGON.A2_combine_ll,SI_ftype_SISI,2) +// +def int_hexagon_A2_combine_ll : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.combine.ll">; +// +// BUILTIN_INFO(HEXAGON.A2_tfril,SI_ftype_SISI,2) +// +def int_hexagon_A2_tfril : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.tfril">; +// +// BUILTIN_INFO(HEXAGON.A2_tfrih,SI_ftype_SISI,2) +// +def int_hexagon_A2_tfrih : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.tfrih">; +// +// BUILTIN_INFO(HEXAGON.A2_and,SI_ftype_SISI,2) +// +def int_hexagon_A2_and : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.and">; +// +// BUILTIN_INFO(HEXAGON.A2_or,SI_ftype_SISI,2) +// +def int_hexagon_A2_or : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.or">; +// +// BUILTIN_INFO(HEXAGON.A2_xor,SI_ftype_SISI,2) +// +def int_hexagon_A2_xor : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.xor">; +// +// BUILTIN_INFO(HEXAGON.A2_not,SI_ftype_SI,1) +// +def int_hexagon_A2_not : +Hexagon_si_si_Intrinsic<"HEXAGON.A2.not">; +// +// BUILTIN_INFO(HEXAGON.M2_xor_xacc,SI_ftype_SISISI,3) +// +def int_hexagon_M2_xor_xacc : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M2.xor.xacc">; +// +// BUILTIN_INFO(HEXAGON.A2_subri,SI_ftype_SISI,2) +// +def int_hexagon_A2_subri : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.subri">; +// +// BUILTIN_INFO(HEXAGON.A2_andir,SI_ftype_SISI,2) +// +def int_hexagon_A2_andir : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.andir">; +// +// BUILTIN_INFO(HEXAGON.A2_orir,SI_ftype_SISI,2) +// +def int_hexagon_A2_orir : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.orir">; +// +// BUILTIN_INFO(HEXAGON.A2_andp,DI_ftype_DIDI,2) +// +def int_hexagon_A2_andp : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.andp">; +// +// BUILTIN_INFO(HEXAGON.A2_orp,DI_ftype_DIDI,2) +// +def int_hexagon_A2_orp : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.orp">; +// +// BUILTIN_INFO(HEXAGON.A2_xorp,DI_ftype_DIDI,2) +// +def int_hexagon_A2_xorp : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.xorp">; +// +// BUILTIN_INFO(HEXAGON.A2_notp,DI_ftype_DI,1) +// +def int_hexagon_A2_notp : +Hexagon_di_di_Intrinsic<"HEXAGON.A2.notp">; +// +// BUILTIN_INFO(HEXAGON.A2_sxtw,DI_ftype_SI,1) +// +def int_hexagon_A2_sxtw : +Hexagon_di_si_Intrinsic<"HEXAGON.A2.sxtw">; +// +// BUILTIN_INFO(HEXAGON.A2_sat,SI_ftype_DI,1) +// +def int_hexagon_A2_sat : +Hexagon_si_di_Intrinsic<"HEXAGON.A2.sat">; +// +// BUILTIN_INFO(HEXAGON.A2_sath,SI_ftype_SI,1) +// +def int_hexagon_A2_sath : +Hexagon_si_si_Intrinsic<"HEXAGON.A2.sath">; +// +// BUILTIN_INFO(HEXAGON.A2_satuh,SI_ftype_SI,1) +// +def int_hexagon_A2_satuh : +Hexagon_si_si_Intrinsic<"HEXAGON.A2.satuh">; +// +// BUILTIN_INFO(HEXAGON.A2_satub,SI_ftype_SI,1) +// +def int_hexagon_A2_satub : +Hexagon_si_si_Intrinsic<"HEXAGON.A2.satub">; +// +// BUILTIN_INFO(HEXAGON.A2_satb,SI_ftype_SI,1) +// +def int_hexagon_A2_satb : +Hexagon_si_si_Intrinsic<"HEXAGON.A2.satb">; +// +// BUILTIN_INFO(HEXAGON.A2_vaddub,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vaddub : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vaddub">; +// +// BUILTIN_INFO(HEXAGON.A2_vaddubs,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vaddubs : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vaddubs">; +// +// BUILTIN_INFO(HEXAGON.A2_vaddh,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vaddh : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vaddh">; +// +// BUILTIN_INFO(HEXAGON.A2_vaddhs,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vaddhs : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vaddhs">; +// +// BUILTIN_INFO(HEXAGON.A2_vadduhs,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vadduhs : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vadduhs">; +// +// BUILTIN_INFO(HEXAGON.A2_vaddw,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vaddw : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vaddw">; +// +// BUILTIN_INFO(HEXAGON.A2_vaddws,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vaddws : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vaddws">; +// +// BUILTIN_INFO(HEXAGON.A2_svavgh,SI_ftype_SISI,2) +// +def int_hexagon_A2_svavgh : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.svavgh">; +// +// BUILTIN_INFO(HEXAGON.A2_svavghs,SI_ftype_SISI,2) +// +def int_hexagon_A2_svavghs : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.svavghs">; +// +// BUILTIN_INFO(HEXAGON.A2_svnavgh,SI_ftype_SISI,2) +// +def int_hexagon_A2_svnavgh : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.svnavgh">; +// +// BUILTIN_INFO(HEXAGON.A2_svaddh,SI_ftype_SISI,2) +// +def int_hexagon_A2_svaddh : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.svaddh">; +// +// BUILTIN_INFO(HEXAGON.A2_svaddhs,SI_ftype_SISI,2) +// +def int_hexagon_A2_svaddhs : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.svaddhs">; +// +// BUILTIN_INFO(HEXAGON.A2_svadduhs,SI_ftype_SISI,2) +// +def int_hexagon_A2_svadduhs : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.svadduhs">; +// +// BUILTIN_INFO(HEXAGON.A2_svsubh,SI_ftype_SISI,2) +// +def int_hexagon_A2_svsubh : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.svsubh">; +// +// BUILTIN_INFO(HEXAGON.A2_svsubhs,SI_ftype_SISI,2) +// +def int_hexagon_A2_svsubhs : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.svsubhs">; +// +// BUILTIN_INFO(HEXAGON.A2_svsubuhs,SI_ftype_SISI,2) +// +def int_hexagon_A2_svsubuhs : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A2.svsubuhs">; +// +// BUILTIN_INFO(HEXAGON.A2_vraddub,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vraddub : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vraddub">; +// +// BUILTIN_INFO(HEXAGON.A2_vraddub_acc,DI_ftype_DIDIDI,3) +// +def int_hexagon_A2_vraddub_acc : +Hexagon_di_dididi_Intrinsic<"HEXAGON.A2.vraddub.acc">; +// +// BUILTIN_INFO(HEXAGON.M2_vradduh,SI_ftype_DIDI,2) +// +def int_hexagon_M2_vradduh : +Hexagon_si_didi_Intrinsic<"HEXAGON.M2.vradduh">; +// +// BUILTIN_INFO(HEXAGON.A2_vsubub,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vsubub : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vsubub">; +// +// BUILTIN_INFO(HEXAGON.A2_vsububs,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vsububs : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vsububs">; +// +// BUILTIN_INFO(HEXAGON.A2_vsubh,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vsubh : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vsubh">; +// +// BUILTIN_INFO(HEXAGON.A2_vsubhs,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vsubhs : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vsubhs">; +// +// BUILTIN_INFO(HEXAGON.A2_vsubuhs,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vsubuhs : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vsubuhs">; +// +// BUILTIN_INFO(HEXAGON.A2_vsubw,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vsubw : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vsubw">; +// +// BUILTIN_INFO(HEXAGON.A2_vsubws,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vsubws : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vsubws">; +// +// BUILTIN_INFO(HEXAGON.A2_vabsh,DI_ftype_DI,1) +// +def int_hexagon_A2_vabsh : +Hexagon_di_di_Intrinsic<"HEXAGON.A2.vabsh">; +// +// BUILTIN_INFO(HEXAGON.A2_vabshsat,DI_ftype_DI,1) +// +def int_hexagon_A2_vabshsat : +Hexagon_di_di_Intrinsic<"HEXAGON.A2.vabshsat">; +// +// BUILTIN_INFO(HEXAGON.A2_vabsw,DI_ftype_DI,1) +// +def int_hexagon_A2_vabsw : +Hexagon_di_di_Intrinsic<"HEXAGON.A2.vabsw">; +// +// BUILTIN_INFO(HEXAGON.A2_vabswsat,DI_ftype_DI,1) +// +def int_hexagon_A2_vabswsat : +Hexagon_di_di_Intrinsic<"HEXAGON.A2.vabswsat">; +// +// BUILTIN_INFO(HEXAGON.M2_vabsdiffw,DI_ftype_DIDI,2) +// +def int_hexagon_M2_vabsdiffw : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.vabsdiffw">; +// +// BUILTIN_INFO(HEXAGON.M2_vabsdiffh,DI_ftype_DIDI,2) +// +def int_hexagon_M2_vabsdiffh : +Hexagon_di_didi_Intrinsic<"HEXAGON.M2.vabsdiffh">; +// +// BUILTIN_INFO(HEXAGON.A2_vrsadub,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vrsadub : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vrsadub">; +// +// BUILTIN_INFO(HEXAGON.A2_vrsadub_acc,DI_ftype_DIDIDI,3) +// +def int_hexagon_A2_vrsadub_acc : +Hexagon_di_dididi_Intrinsic<"HEXAGON.A2.vrsadub.acc">; +// +// BUILTIN_INFO(HEXAGON.A2_vavgub,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vavgub : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vavgub">; +// +// BUILTIN_INFO(HEXAGON.A2_vavguh,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vavguh : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vavguh">; +// +// BUILTIN_INFO(HEXAGON.A2_vavgh,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vavgh : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vavgh">; +// +// BUILTIN_INFO(HEXAGON.A2_vnavgh,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vnavgh : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vnavgh">; +// +// BUILTIN_INFO(HEXAGON.A2_vavgw,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vavgw : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vavgw">; +// +// BUILTIN_INFO(HEXAGON.A2_vnavgw,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vnavgw : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vnavgw">; +// +// BUILTIN_INFO(HEXAGON.A2_vavgwr,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vavgwr : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vavgwr">; +// +// BUILTIN_INFO(HEXAGON.A2_vnavgwr,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vnavgwr : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vnavgwr">; +// +// BUILTIN_INFO(HEXAGON.A2_vavgwcr,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vavgwcr : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vavgwcr">; +// +// BUILTIN_INFO(HEXAGON.A2_vnavgwcr,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vnavgwcr : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vnavgwcr">; +// +// BUILTIN_INFO(HEXAGON.A2_vavghcr,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vavghcr : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vavghcr">; +// +// BUILTIN_INFO(HEXAGON.A2_vnavghcr,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vnavghcr : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vnavghcr">; +// +// BUILTIN_INFO(HEXAGON.A2_vavguw,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vavguw : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vavguw">; +// +// BUILTIN_INFO(HEXAGON.A2_vavguwr,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vavguwr : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vavguwr">; +// +// BUILTIN_INFO(HEXAGON.A2_vavgubr,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vavgubr : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vavgubr">; +// +// BUILTIN_INFO(HEXAGON.A2_vavguhr,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vavguhr : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vavguhr">; +// +// BUILTIN_INFO(HEXAGON.A2_vavghr,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vavghr : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vavghr">; +// +// BUILTIN_INFO(HEXAGON.A2_vnavghr,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vnavghr : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vnavghr">; +// +// BUILTIN_INFO(HEXAGON.A2_vminh,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vminh : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vminh">; +// +// BUILTIN_INFO(HEXAGON.A2_vmaxh,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vmaxh : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vmaxh">; +// +// BUILTIN_INFO(HEXAGON.A2_vminub,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vminub : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vminub">; +// +// BUILTIN_INFO(HEXAGON.A2_vmaxub,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vmaxub : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vmaxub">; +// +// BUILTIN_INFO(HEXAGON.A2_vminuh,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vminuh : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vminuh">; +// +// BUILTIN_INFO(HEXAGON.A2_vmaxuh,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vmaxuh : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vmaxuh">; +// +// BUILTIN_INFO(HEXAGON.A2_vminw,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vminw : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vminw">; +// +// BUILTIN_INFO(HEXAGON.A2_vmaxw,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vmaxw : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vmaxw">; +// +// BUILTIN_INFO(HEXAGON.A2_vminuw,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vminuw : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vminuw">; +// +// BUILTIN_INFO(HEXAGON.A2_vmaxuw,DI_ftype_DIDI,2) +// +def int_hexagon_A2_vmaxuw : +Hexagon_di_didi_Intrinsic<"HEXAGON.A2.vmaxuw">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_r_r,SI_ftype_SISI,2) +// +def int_hexagon_S2_asr_r_r : +Hexagon_si_sisi_Intrinsic<"HEXAGON.S2.asr.r.r">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_r_r,SI_ftype_SISI,2) +// +def int_hexagon_S2_asl_r_r : +Hexagon_si_sisi_Intrinsic<"HEXAGON.S2.asl.r.r">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_r_r,SI_ftype_SISI,2) +// +def int_hexagon_S2_lsr_r_r : +Hexagon_si_sisi_Intrinsic<"HEXAGON.S2.lsr.r.r">; +// +// BUILTIN_INFO(HEXAGON.S2_lsl_r_r,SI_ftype_SISI,2) +// +def int_hexagon_S2_lsl_r_r : +Hexagon_si_sisi_Intrinsic<"HEXAGON.S2.lsl.r.r">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_r_p,DI_ftype_DISI,2) +// +def int_hexagon_S2_asr_r_p : +Hexagon_di_disi_Intrinsic<"HEXAGON.S2.asr.r.p">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_r_p,DI_ftype_DISI,2) +// +def int_hexagon_S2_asl_r_p : +Hexagon_di_disi_Intrinsic<"HEXAGON.S2.asl.r.p">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_r_p,DI_ftype_DISI,2) +// +def int_hexagon_S2_lsr_r_p : +Hexagon_di_disi_Intrinsic<"HEXAGON.S2.lsr.r.p">; +// +// BUILTIN_INFO(HEXAGON.S2_lsl_r_p,DI_ftype_DISI,2) +// +def int_hexagon_S2_lsl_r_p : +Hexagon_di_disi_Intrinsic<"HEXAGON.S2.lsl.r.p">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_r_r_acc,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asr_r_r_acc : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.asr.r.r.acc">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_r_r_acc,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asl_r_r_acc : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.asl.r.r.acc">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_r_r_acc,SI_ftype_SISISI,3) +// +def int_hexagon_S2_lsr_r_r_acc : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.lsr.r.r.acc">; +// +// BUILTIN_INFO(HEXAGON.S2_lsl_r_r_acc,SI_ftype_SISISI,3) +// +def int_hexagon_S2_lsl_r_r_acc : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.lsl.r.r.acc">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_r_p_acc,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asr_r_p_acc : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.asr.r.p.acc">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_r_p_acc,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asl_r_p_acc : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.asl.r.p.acc">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_r_p_acc,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_lsr_r_p_acc : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.lsr.r.p.acc">; +// +// BUILTIN_INFO(HEXAGON.S2_lsl_r_p_acc,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_lsl_r_p_acc : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.lsl.r.p.acc">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_r_r_nac,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asr_r_r_nac : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.asr.r.r.nac">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_r_r_nac,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asl_r_r_nac : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.asl.r.r.nac">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_r_r_nac,SI_ftype_SISISI,3) +// +def int_hexagon_S2_lsr_r_r_nac : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.lsr.r.r.nac">; +// +// BUILTIN_INFO(HEXAGON.S2_lsl_r_r_nac,SI_ftype_SISISI,3) +// +def int_hexagon_S2_lsl_r_r_nac : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.lsl.r.r.nac">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_r_p_nac,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asr_r_p_nac : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.asr.r.p.nac">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_r_p_nac,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asl_r_p_nac : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.asl.r.p.nac">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_r_p_nac,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_lsr_r_p_nac : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.lsr.r.p.nac">; +// +// BUILTIN_INFO(HEXAGON.S2_lsl_r_p_nac,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_lsl_r_p_nac : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.lsl.r.p.nac">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_r_r_and,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asr_r_r_and : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.asr.r.r.and">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_r_r_and,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asl_r_r_and : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.asl.r.r.and">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_r_r_and,SI_ftype_SISISI,3) +// +def int_hexagon_S2_lsr_r_r_and : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.lsr.r.r.and">; +// +// BUILTIN_INFO(HEXAGON.S2_lsl_r_r_and,SI_ftype_SISISI,3) +// +def int_hexagon_S2_lsl_r_r_and : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.lsl.r.r.and">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_r_r_or,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asr_r_r_or : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.asr.r.r.or">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_r_r_or,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asl_r_r_or : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.asl.r.r.or">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_r_r_or,SI_ftype_SISISI,3) +// +def int_hexagon_S2_lsr_r_r_or : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.lsr.r.r.or">; +// +// BUILTIN_INFO(HEXAGON.S2_lsl_r_r_or,SI_ftype_SISISI,3) +// +def int_hexagon_S2_lsl_r_r_or : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.lsl.r.r.or">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_r_p_and,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asr_r_p_and : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.asr.r.p.and">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_r_p_and,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asl_r_p_and : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.asl.r.p.and">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_r_p_and,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_lsr_r_p_and : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.lsr.r.p.and">; +// +// BUILTIN_INFO(HEXAGON.S2_lsl_r_p_and,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_lsl_r_p_and : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.lsl.r.p.and">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_r_p_or,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asr_r_p_or : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.asr.r.p.or">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_r_p_or,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asl_r_p_or : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.asl.r.p.or">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_r_p_or,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_lsr_r_p_or : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.lsr.r.p.or">; +// +// BUILTIN_INFO(HEXAGON.S2_lsl_r_p_or,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_lsl_r_p_or : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.lsl.r.p.or">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_r_r_sat,SI_ftype_SISI,2) +// +def int_hexagon_S2_asr_r_r_sat : +Hexagon_si_sisi_Intrinsic<"HEXAGON.S2.asr.r.r.sat">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_r_r_sat,SI_ftype_SISI,2) +// +def int_hexagon_S2_asl_r_r_sat : +Hexagon_si_sisi_Intrinsic<"HEXAGON.S2.asl.r.r.sat">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_r,SI_ftype_SISI,2) +// +def int_hexagon_S2_asr_i_r : +Hexagon_si_sisi_Intrinsic<"HEXAGON.S2.asr.i.r">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_i_r,SI_ftype_SISI,2) +// +def int_hexagon_S2_lsr_i_r : +Hexagon_si_sisi_Intrinsic<"HEXAGON.S2.lsr.i.r">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_i_r,SI_ftype_SISI,2) +// +def int_hexagon_S2_asl_i_r : +Hexagon_si_sisi_Intrinsic<"HEXAGON.S2.asl.i.r">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_p,DI_ftype_DISI,2) +// +def int_hexagon_S2_asr_i_p : +Hexagon_di_disi_Intrinsic<"HEXAGON.S2.asr.i.p">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_i_p,DI_ftype_DISI,2) +// +def int_hexagon_S2_lsr_i_p : +Hexagon_di_disi_Intrinsic<"HEXAGON.S2.lsr.i.p">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_i_p,DI_ftype_DISI,2) +// +def int_hexagon_S2_asl_i_p : +Hexagon_di_disi_Intrinsic<"HEXAGON.S2.asl.i.p">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_r_acc,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asr_i_r_acc : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.asr.i.r.acc">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_i_r_acc,SI_ftype_SISISI,3) +// +def int_hexagon_S2_lsr_i_r_acc : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.lsr.i.r.acc">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_i_r_acc,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asl_i_r_acc : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.asl.i.r.acc">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_p_acc,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asr_i_p_acc : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.asr.i.p.acc">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_i_p_acc,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_lsr_i_p_acc : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.lsr.i.p.acc">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_i_p_acc,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asl_i_p_acc : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.asl.i.p.acc">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_r_nac,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asr_i_r_nac : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.asr.i.r.nac">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_i_r_nac,SI_ftype_SISISI,3) +// +def int_hexagon_S2_lsr_i_r_nac : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.lsr.i.r.nac">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_i_r_nac,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asl_i_r_nac : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.asl.i.r.nac">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_p_nac,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asr_i_p_nac : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.asr.i.p.nac">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_i_p_nac,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_lsr_i_p_nac : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.lsr.i.p.nac">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_i_p_nac,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asl_i_p_nac : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.asl.i.p.nac">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_i_r_xacc,SI_ftype_SISISI,3) +// +def int_hexagon_S2_lsr_i_r_xacc : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.lsr.i.r.xacc">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_i_r_xacc,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asl_i_r_xacc : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.asl.i.r.xacc">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_i_p_xacc,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_lsr_i_p_xacc : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.lsr.i.p.xacc">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_i_p_xacc,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asl_i_p_xacc : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.asl.i.p.xacc">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_r_and,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asr_i_r_and : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.asr.i.r.and">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_i_r_and,SI_ftype_SISISI,3) +// +def int_hexagon_S2_lsr_i_r_and : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.lsr.i.r.and">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_i_r_and,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asl_i_r_and : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.asl.i.r.and">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_r_or,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asr_i_r_or : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.asr.i.r.or">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_i_r_or,SI_ftype_SISISI,3) +// +def int_hexagon_S2_lsr_i_r_or : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.lsr.i.r.or">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_i_r_or,SI_ftype_SISISI,3) +// +def int_hexagon_S2_asl_i_r_or : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.asl.i.r.or">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_p_and,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asr_i_p_and : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.asr.i.p.and">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_i_p_and,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_lsr_i_p_and : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.lsr.i.p.and">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_i_p_and,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asl_i_p_and : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.asl.i.p.and">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_p_or,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asr_i_p_or : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.asr.i.p.or">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_i_p_or,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_lsr_i_p_or : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.lsr.i.p.or">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_i_p_or,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_asl_i_p_or : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.asl.i.p.or">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_i_r_sat,SI_ftype_SISI,2) +// +def int_hexagon_S2_asl_i_r_sat : +Hexagon_si_sisi_Intrinsic<"HEXAGON.S2.asl.i.r.sat">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_r_rnd,SI_ftype_SISI,2) +// +def int_hexagon_S2_asr_i_r_rnd : +Hexagon_si_sisi_Intrinsic<"HEXAGON.S2.asr.i.r.rnd">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_r_rnd_goodsyntax,SI_ftype_SISI,2) +// +def int_hexagon_S2_asr_i_r_rnd_goodsyntax : +Hexagon_si_sisi_Intrinsic<"HEXAGON.S2.asr.i.r.rnd.goodsyntax">; +// +// BUILTIN_INFO(HEXAGON.S2_addasl_rrri,SI_ftype_SISISI,3) +// +def int_hexagon_S2_addasl_rrri : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.addasl.rrri">; +// +// BUILTIN_INFO(HEXAGON.S2_valignib,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_valignib : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.valignib">; +// +// BUILTIN_INFO(HEXAGON.S2_valignrb,DI_ftype_DIDIQI,3) +// +def int_hexagon_S2_valignrb : +Hexagon_di_didiqi_Intrinsic<"HEXAGON.S2.valignrb">; +// +// BUILTIN_INFO(HEXAGON.S2_vspliceib,DI_ftype_DIDISI,3) +// +def int_hexagon_S2_vspliceib : +Hexagon_di_didisi_Intrinsic<"HEXAGON.S2.vspliceib">; +// +// BUILTIN_INFO(HEXAGON.S2_vsplicerb,DI_ftype_DIDIQI,3) +// +def int_hexagon_S2_vsplicerb : +Hexagon_di_didiqi_Intrinsic<"HEXAGON.S2.vsplicerb">; +// +// BUILTIN_INFO(HEXAGON.S2_vsplatrh,DI_ftype_SI,1) +// +def int_hexagon_S2_vsplatrh : +Hexagon_di_si_Intrinsic<"HEXAGON.S2.vsplatrh">; +// +// BUILTIN_INFO(HEXAGON.S2_vsplatrb,SI_ftype_SI,1) +// +def int_hexagon_S2_vsplatrb : +Hexagon_si_si_Intrinsic<"HEXAGON.S2.vsplatrb">; +// +// BUILTIN_INFO(HEXAGON.S2_insert,SI_ftype_SISISISI,4) +// +def int_hexagon_S2_insert : +Hexagon_si_sisisisi_Intrinsic<"HEXAGON.S2.insert">; +// +// BUILTIN_INFO(HEXAGON.S2_tableidxb_goodsyntax,SI_ftype_SISISISI,4) +// +def int_hexagon_S2_tableidxb_goodsyntax : +Hexagon_si_sisisisi_Intrinsic<"HEXAGON.S2.tableidxb.goodsyntax">; +// +// BUILTIN_INFO(HEXAGON.S2_tableidxh_goodsyntax,SI_ftype_SISISISI,4) +// +def int_hexagon_S2_tableidxh_goodsyntax : +Hexagon_si_sisisisi_Intrinsic<"HEXAGON.S2.tableidxh.goodsyntax">; +// +// BUILTIN_INFO(HEXAGON.S2_tableidxw_goodsyntax,SI_ftype_SISISISI,4) +// +def int_hexagon_S2_tableidxw_goodsyntax : +Hexagon_si_sisisisi_Intrinsic<"HEXAGON.S2.tableidxw.goodsyntax">; +// +// BUILTIN_INFO(HEXAGON.S2_tableidxd_goodsyntax,SI_ftype_SISISISI,4) +// +def int_hexagon_S2_tableidxd_goodsyntax : +Hexagon_si_sisisisi_Intrinsic<"HEXAGON.S2.tableidxd.goodsyntax">; +// +// BUILTIN_INFO(HEXAGON.S2_extractu,SI_ftype_SISISI,3) +// +def int_hexagon_S2_extractu : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S2.extractu">; +// +// BUILTIN_INFO(HEXAGON.S2_insertp,DI_ftype_DIDISISI,4) +// +def int_hexagon_S2_insertp : +Hexagon_di_didisisi_Intrinsic<"HEXAGON.S2.insertp">; +// +// BUILTIN_INFO(HEXAGON.S2_extractup,DI_ftype_DISISI,3) +// +def int_hexagon_S2_extractup : +Hexagon_di_disisi_Intrinsic<"HEXAGON.S2.extractup">; +// +// BUILTIN_INFO(HEXAGON.S2_insert_rp,SI_ftype_SISIDI,3) +// +def int_hexagon_S2_insert_rp : +Hexagon_si_sisidi_Intrinsic<"HEXAGON.S2.insert.rp">; +// +// BUILTIN_INFO(HEXAGON.S2_extractu_rp,SI_ftype_SIDI,2) +// +def int_hexagon_S2_extractu_rp : +Hexagon_si_sidi_Intrinsic<"HEXAGON.S2.extractu.rp">; +// +// BUILTIN_INFO(HEXAGON.S2_insertp_rp,DI_ftype_DIDIDI,3) +// +def int_hexagon_S2_insertp_rp : +Hexagon_di_dididi_Intrinsic<"HEXAGON.S2.insertp.rp">; +// +// BUILTIN_INFO(HEXAGON.S2_extractup_rp,DI_ftype_DIDI,2) +// +def int_hexagon_S2_extractup_rp : +Hexagon_di_didi_Intrinsic<"HEXAGON.S2.extractup.rp">; +// +// BUILTIN_INFO(HEXAGON.S2_tstbit_i,QI_ftype_SISI,2) +// +def int_hexagon_S2_tstbit_i : +Hexagon_qi_sisi_Intrinsic<"HEXAGON.S2.tstbit.i">; +// +// BUILTIN_INFO(HEXAGON.S2_setbit_i,SI_ftype_SISI,2) +// +def int_hexagon_S2_setbit_i : +Hexagon_si_sisi_Intrinsic<"HEXAGON.S2.setbit.i">; +// +// BUILTIN_INFO(HEXAGON.S2_togglebit_i,SI_ftype_SISI,2) +// +def int_hexagon_S2_togglebit_i : +Hexagon_si_sisi_Intrinsic<"HEXAGON.S2.togglebit.i">; +// +// BUILTIN_INFO(HEXAGON.S2_clrbit_i,SI_ftype_SISI,2) +// +def int_hexagon_S2_clrbit_i : +Hexagon_si_sisi_Intrinsic<"HEXAGON.S2.clrbit.i">; +// +// BUILTIN_INFO(HEXAGON.S2_tstbit_r,QI_ftype_SISI,2) +// +def int_hexagon_S2_tstbit_r : +Hexagon_qi_sisi_Intrinsic<"HEXAGON.S2.tstbit.r">; +// +// BUILTIN_INFO(HEXAGON.S2_setbit_r,SI_ftype_SISI,2) +// +def int_hexagon_S2_setbit_r : +Hexagon_si_sisi_Intrinsic<"HEXAGON.S2.setbit.r">; +// +// BUILTIN_INFO(HEXAGON.S2_togglebit_r,SI_ftype_SISI,2) +// +def int_hexagon_S2_togglebit_r : +Hexagon_si_sisi_Intrinsic<"HEXAGON.S2.togglebit.r">; +// +// BUILTIN_INFO(HEXAGON.S2_clrbit_r,SI_ftype_SISI,2) +// +def int_hexagon_S2_clrbit_r : +Hexagon_si_sisi_Intrinsic<"HEXAGON.S2.clrbit.r">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_vh,DI_ftype_DISI,2) +// +def int_hexagon_S2_asr_i_vh : +Hexagon_di_disi_Intrinsic<"HEXAGON.S2.asr.i.vh">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_i_vh,DI_ftype_DISI,2) +// +def int_hexagon_S2_lsr_i_vh : +Hexagon_di_disi_Intrinsic<"HEXAGON.S2.lsr.i.vh">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_i_vh,DI_ftype_DISI,2) +// +def int_hexagon_S2_asl_i_vh : +Hexagon_di_disi_Intrinsic<"HEXAGON.S2.asl.i.vh">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_r_vh,DI_ftype_DISI,2) +// +def int_hexagon_S2_asr_r_vh : +Hexagon_di_disi_Intrinsic<"HEXAGON.S2.asr.r.vh">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_r_vh,DI_ftype_DISI,2) +// +def int_hexagon_S2_asl_r_vh : +Hexagon_di_disi_Intrinsic<"HEXAGON.S2.asl.r.vh">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_r_vh,DI_ftype_DISI,2) +// +def int_hexagon_S2_lsr_r_vh : +Hexagon_di_disi_Intrinsic<"HEXAGON.S2.lsr.r.vh">; +// +// BUILTIN_INFO(HEXAGON.S2_lsl_r_vh,DI_ftype_DISI,2) +// +def int_hexagon_S2_lsl_r_vh : +Hexagon_di_disi_Intrinsic<"HEXAGON.S2.lsl.r.vh">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_vw,DI_ftype_DISI,2) +// +def int_hexagon_S2_asr_i_vw : +Hexagon_di_disi_Intrinsic<"HEXAGON.S2.asr.i.vw">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_i_svw_trun,SI_ftype_DISI,2) +// +def int_hexagon_S2_asr_i_svw_trun : +Hexagon_si_disi_Intrinsic<"HEXAGON.S2.asr.i.svw.trun">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_r_svw_trun,SI_ftype_DISI,2) +// +def int_hexagon_S2_asr_r_svw_trun : +Hexagon_si_disi_Intrinsic<"HEXAGON.S2.asr.r.svw.trun">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_i_vw,DI_ftype_DISI,2) +// +def int_hexagon_S2_lsr_i_vw : +Hexagon_di_disi_Intrinsic<"HEXAGON.S2.lsr.i.vw">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_i_vw,DI_ftype_DISI,2) +// +def int_hexagon_S2_asl_i_vw : +Hexagon_di_disi_Intrinsic<"HEXAGON.S2.asl.i.vw">; +// +// BUILTIN_INFO(HEXAGON.S2_asr_r_vw,DI_ftype_DISI,2) +// +def int_hexagon_S2_asr_r_vw : +Hexagon_di_disi_Intrinsic<"HEXAGON.S2.asr.r.vw">; +// +// BUILTIN_INFO(HEXAGON.S2_asl_r_vw,DI_ftype_DISI,2) +// +def int_hexagon_S2_asl_r_vw : +Hexagon_di_disi_Intrinsic<"HEXAGON.S2.asl.r.vw">; +// +// BUILTIN_INFO(HEXAGON.S2_lsr_r_vw,DI_ftype_DISI,2) +// +def int_hexagon_S2_lsr_r_vw : +Hexagon_di_disi_Intrinsic<"HEXAGON.S2.lsr.r.vw">; +// +// BUILTIN_INFO(HEXAGON.S2_lsl_r_vw,DI_ftype_DISI,2) +// +def int_hexagon_S2_lsl_r_vw : +Hexagon_di_disi_Intrinsic<"HEXAGON.S2.lsl.r.vw">; +// +// BUILTIN_INFO(HEXAGON.S2_vrndpackwh,SI_ftype_DI,1) +// +def int_hexagon_S2_vrndpackwh : +Hexagon_si_di_Intrinsic<"HEXAGON.S2.vrndpackwh">; +// +// BUILTIN_INFO(HEXAGON.S2_vrndpackwhs,SI_ftype_DI,1) +// +def int_hexagon_S2_vrndpackwhs : +Hexagon_si_di_Intrinsic<"HEXAGON.S2.vrndpackwhs">; +// +// BUILTIN_INFO(HEXAGON.S2_vsxtbh,DI_ftype_SI,1) +// +def int_hexagon_S2_vsxtbh : +Hexagon_di_si_Intrinsic<"HEXAGON.S2.vsxtbh">; +// +// BUILTIN_INFO(HEXAGON.S2_vzxtbh,DI_ftype_SI,1) +// +def int_hexagon_S2_vzxtbh : +Hexagon_di_si_Intrinsic<"HEXAGON.S2.vzxtbh">; +// +// BUILTIN_INFO(HEXAGON.S2_vsathub,SI_ftype_DI,1) +// +def int_hexagon_S2_vsathub : +Hexagon_si_di_Intrinsic<"HEXAGON.S2.vsathub">; +// +// BUILTIN_INFO(HEXAGON.S2_svsathub,SI_ftype_SI,1) +// +def int_hexagon_S2_svsathub : +Hexagon_si_si_Intrinsic<"HEXAGON.S2.svsathub">; +// +// BUILTIN_INFO(HEXAGON.S2_svsathb,SI_ftype_SI,1) +// +def int_hexagon_S2_svsathb : +Hexagon_si_si_Intrinsic<"HEXAGON.S2.svsathb">; +// +// BUILTIN_INFO(HEXAGON.S2_vsathb,SI_ftype_DI,1) +// +def int_hexagon_S2_vsathb : +Hexagon_si_di_Intrinsic<"HEXAGON.S2.vsathb">; +// +// BUILTIN_INFO(HEXAGON.S2_vtrunohb,SI_ftype_DI,1) +// +def int_hexagon_S2_vtrunohb : +Hexagon_si_di_Intrinsic<"HEXAGON.S2.vtrunohb">; +// +// BUILTIN_INFO(HEXAGON.S2_vtrunewh,DI_ftype_DIDI,2) +// +def int_hexagon_S2_vtrunewh : +Hexagon_di_didi_Intrinsic<"HEXAGON.S2.vtrunewh">; +// +// BUILTIN_INFO(HEXAGON.S2_vtrunowh,DI_ftype_DIDI,2) +// +def int_hexagon_S2_vtrunowh : +Hexagon_di_didi_Intrinsic<"HEXAGON.S2.vtrunowh">; +// +// BUILTIN_INFO(HEXAGON.S2_vtrunehb,SI_ftype_DI,1) +// +def int_hexagon_S2_vtrunehb : +Hexagon_si_di_Intrinsic<"HEXAGON.S2.vtrunehb">; +// +// BUILTIN_INFO(HEXAGON.S2_vsxthw,DI_ftype_SI,1) +// +def int_hexagon_S2_vsxthw : +Hexagon_di_si_Intrinsic<"HEXAGON.S2.vsxthw">; +// +// BUILTIN_INFO(HEXAGON.S2_vzxthw,DI_ftype_SI,1) +// +def int_hexagon_S2_vzxthw : +Hexagon_di_si_Intrinsic<"HEXAGON.S2.vzxthw">; +// +// BUILTIN_INFO(HEXAGON.S2_vsatwh,SI_ftype_DI,1) +// +def int_hexagon_S2_vsatwh : +Hexagon_si_di_Intrinsic<"HEXAGON.S2.vsatwh">; +// +// BUILTIN_INFO(HEXAGON.S2_vsatwuh,SI_ftype_DI,1) +// +def int_hexagon_S2_vsatwuh : +Hexagon_si_di_Intrinsic<"HEXAGON.S2.vsatwuh">; +// +// BUILTIN_INFO(HEXAGON.S2_packhl,DI_ftype_SISI,2) +// +def int_hexagon_S2_packhl : +Hexagon_di_sisi_Intrinsic<"HEXAGON.S2.packhl">; +// +// BUILTIN_INFO(HEXAGON.A2_swiz,SI_ftype_SI,1) +// +def int_hexagon_A2_swiz : +Hexagon_si_si_Intrinsic<"HEXAGON.A2.swiz">; +// +// BUILTIN_INFO(HEXAGON.S2_vsathub_nopack,DI_ftype_DI,1) +// +def int_hexagon_S2_vsathub_nopack : +Hexagon_di_di_Intrinsic<"HEXAGON.S2.vsathub.nopack">; +// +// BUILTIN_INFO(HEXAGON.S2_vsathb_nopack,DI_ftype_DI,1) +// +def int_hexagon_S2_vsathb_nopack : +Hexagon_di_di_Intrinsic<"HEXAGON.S2.vsathb.nopack">; +// +// BUILTIN_INFO(HEXAGON.S2_vsatwh_nopack,DI_ftype_DI,1) +// +def int_hexagon_S2_vsatwh_nopack : +Hexagon_di_di_Intrinsic<"HEXAGON.S2.vsatwh.nopack">; +// +// BUILTIN_INFO(HEXAGON.S2_vsatwuh_nopack,DI_ftype_DI,1) +// +def int_hexagon_S2_vsatwuh_nopack : +Hexagon_di_di_Intrinsic<"HEXAGON.S2.vsatwuh.nopack">; +// +// BUILTIN_INFO(HEXAGON.S2_shuffob,DI_ftype_DIDI,2) +// +def int_hexagon_S2_shuffob : +Hexagon_di_didi_Intrinsic<"HEXAGON.S2.shuffob">; +// +// BUILTIN_INFO(HEXAGON.S2_shuffeb,DI_ftype_DIDI,2) +// +def int_hexagon_S2_shuffeb : +Hexagon_di_didi_Intrinsic<"HEXAGON.S2.shuffeb">; +// +// BUILTIN_INFO(HEXAGON.S2_shuffoh,DI_ftype_DIDI,2) +// +def int_hexagon_S2_shuffoh : +Hexagon_di_didi_Intrinsic<"HEXAGON.S2.shuffoh">; +// +// BUILTIN_INFO(HEXAGON.S2_shuffeh,DI_ftype_DIDI,2) +// +def int_hexagon_S2_shuffeh : +Hexagon_di_didi_Intrinsic<"HEXAGON.S2.shuffeh">; +// +// BUILTIN_INFO(HEXAGON.S2_parityp,SI_ftype_DIDI,2) +// +def int_hexagon_S2_parityp : +Hexagon_si_didi_Intrinsic<"HEXAGON.S2.parityp">; +// +// BUILTIN_INFO(HEXAGON.S2_lfsp,DI_ftype_DIDI,2) +// +def int_hexagon_S2_lfsp : +Hexagon_di_didi_Intrinsic<"HEXAGON.S2.lfsp">; +// +// BUILTIN_INFO(HEXAGON.S2_clbnorm,SI_ftype_SI,1) +// +def int_hexagon_S2_clbnorm : +Hexagon_si_si_Intrinsic<"HEXAGON.S2.clbnorm">; +// +// BUILTIN_INFO(HEXAGON.S2_clb,SI_ftype_SI,1) +// +def int_hexagon_S2_clb : +Hexagon_si_si_Intrinsic<"HEXAGON.S2.clb">; +// +// BUILTIN_INFO(HEXAGON.S2_cl0,SI_ftype_SI,1) +// +def int_hexagon_S2_cl0 : +Hexagon_si_si_Intrinsic<"HEXAGON.S2.cl0">; +// +// BUILTIN_INFO(HEXAGON.S2_cl1,SI_ftype_SI,1) +// +def int_hexagon_S2_cl1 : +Hexagon_si_si_Intrinsic<"HEXAGON.S2.cl1">; +// +// BUILTIN_INFO(HEXAGON.S2_clbp,SI_ftype_DI,1) +// +def int_hexagon_S2_clbp : +Hexagon_si_di_Intrinsic<"HEXAGON.S2.clbp">; +// +// BUILTIN_INFO(HEXAGON.S2_cl0p,SI_ftype_DI,1) +// +def int_hexagon_S2_cl0p : +Hexagon_si_di_Intrinsic<"HEXAGON.S2.cl0p">; +// +// BUILTIN_INFO(HEXAGON.S2_cl1p,SI_ftype_DI,1) +// +def int_hexagon_S2_cl1p : +Hexagon_si_di_Intrinsic<"HEXAGON.S2.cl1p">; +// +// BUILTIN_INFO(HEXAGON.S2_brev,SI_ftype_SI,1) +// +def int_hexagon_S2_brev : +Hexagon_si_si_Intrinsic<"HEXAGON.S2.brev">; +// +// BUILTIN_INFO(HEXAGON.S2_ct0,SI_ftype_SI,1) +// +def int_hexagon_S2_ct0 : +Hexagon_si_si_Intrinsic<"HEXAGON.S2.ct0">; +// +// BUILTIN_INFO(HEXAGON.S2_ct1,SI_ftype_SI,1) +// +def int_hexagon_S2_ct1 : +Hexagon_si_si_Intrinsic<"HEXAGON.S2.ct1">; +// +// BUILTIN_INFO(HEXAGON.S2_interleave,DI_ftype_DI,1) +// +def int_hexagon_S2_interleave : +Hexagon_di_di_Intrinsic<"HEXAGON.S2.interleave">; +// +// BUILTIN_INFO(HEXAGON.S2_deinterleave,DI_ftype_DI,1) +// +def int_hexagon_S2_deinterleave : +Hexagon_di_di_Intrinsic<"HEXAGON.S2.deinterleave">; + +// +// BUILTIN_INFO(SI_to_SXTHI_asrh,SI_ftype_SI,1) +// +def int_hexagon_SI_to_SXTHI_asrh : +Hexagon_si_si_Intrinsic<"SI.to.SXTHI.asrh">; + +// +// BUILTIN_INFO(HEXAGON.A4_orn,SI_ftype_SISI,2) +// +def int_hexagon_A4_orn : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A4.orn">; +// +// BUILTIN_INFO(HEXAGON.A4_andn,SI_ftype_SISI,2) +// +def int_hexagon_A4_andn : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A4.andn">; +// +// BUILTIN_INFO(HEXAGON.A4_orn,DI_ftype_DIDI,2) +// +def int_hexagon_A4_ornp : +Hexagon_di_didi_Intrinsic<"HEXAGON.A4.ornp">; +// +// BUILTIN_INFO(HEXAGON.A4_andn,DI_ftype_DIDI,2) +// +def int_hexagon_A4_andnp : +Hexagon_di_didi_Intrinsic<"HEXAGON.A4.andnp">; +// +// BUILTIN_INFO(HEXAGON.A4_combineir,DI_ftype_sisi,2) +// +def int_hexagon_A4_combineir : +Hexagon_di_sisi_Intrinsic<"HEXAGON.A4.combineir">; +// +// BUILTIN_INFO(HEXAGON.A4_combineir,DI_ftype_sisi,2) +// +def int_hexagon_A4_combineri : +Hexagon_di_sisi_Intrinsic<"HEXAGON.A4.combineri">; +// +// BUILTIN_INFO(HEXAGON.C4_cmpneq,QI_ftype_SISI,2) +// +def int_hexagon_C4_cmpneq : +Hexagon_qi_sisi_Intrinsic<"HEXAGON.C4.cmpneq">; +// +// BUILTIN_INFO(HEXAGON.C4_cmpneqi,QI_ftype_SISI,2) +// +def int_hexagon_C4_cmpneqi : +Hexagon_qi_sisi_Intrinsic<"HEXAGON.C4.cmpneqi">; +// +// BUILTIN_INFO(HEXAGON.C4_cmplte,QI_ftype_SISI,2) +// +def int_hexagon_C4_cmplte : +Hexagon_qi_sisi_Intrinsic<"HEXAGON.C4.cmplte">; +// +// BUILTIN_INFO(HEXAGON.C4_cmpltei,QI_ftype_SISI,2) +// +def int_hexagon_C4_cmpltei : +Hexagon_qi_sisi_Intrinsic<"HEXAGON.C4.cmpltei">; +// +// BUILTIN_INFO(HEXAGON.C4_cmplteu,QI_ftype_SISI,2) +// +def int_hexagon_C4_cmplteu : +Hexagon_qi_sisi_Intrinsic<"HEXAGON.C4.cmplteu">; +// +// BUILTIN_INFO(HEXAGON.C4_cmplteui,QI_ftype_SISI,2) +// +def int_hexagon_C4_cmplteui : +Hexagon_qi_sisi_Intrinsic<"HEXAGON.C4.cmplteui">; +// +// BUILTIN_INFO(HEXAGON.A4_rcmpneq,SI_ftype_SISI,2) +// +def int_hexagon_A4_rcmpneq : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A4.rcmpneq">; +// +// BUILTIN_INFO(HEXAGON.A4_rcmpneqi,SI_ftype_SISI,2) +// +def int_hexagon_A4_rcmpneqi : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A4.rcmpneqi">; +// +// BUILTIN_INFO(HEXAGON.A4_rcmpeq,SI_ftype_SISI,2) +// +def int_hexagon_A4_rcmpeq : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A4.rcmpeq">; +// +// BUILTIN_INFO(HEXAGON.A4_rcmpeqi,SI_ftype_SISI,2) +// +def int_hexagon_A4_rcmpeqi : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A4.rcmpeqi">; +// +// BUILTIN_INFO(HEXAGON.C4_fastcorner9,QI_ftype_QIQI,2) +// +def int_hexagon_C4_fastcorner9 : +Hexagon_qi_qiqi_Intrinsic<"HEXAGON.C4.fastcorner9">; +// +// BUILTIN_INFO(HEXAGON.C4_fastcorner9_not,QI_ftype_QIQI,2) +// +def int_hexagon_C4_fastcorner9_not : +Hexagon_qi_qiqi_Intrinsic<"HEXAGON.C4.fastcorner9_not">; +// +// BUILTIN_INFO(HEXAGON.C4_and_andn,QI_ftype_QIQIQI,3) +// +def int_hexagon_C4_and_andn : +Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON.C4.and_andn">; +// +// BUILTIN_INFO(HEXAGON.C4_and_and,QI_ftype_QIQIQI,3) +// +def int_hexagon_C4_and_and : +Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON.C4.and_and">; +// +// BUILTIN_INFO(HEXAGON.C4_and_orn,QI_ftype_QIQIQI,3) +// +def int_hexagon_C4_and_orn : +Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON.C4.and_orn">; +// +// BUILTIN_INFO(HEXAGON.C4_and_or,QI_ftype_QIQIQI,3) +// +def int_hexagon_C4_and_or : +Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON.C4.and_or">; +// +// BUILTIN_INFO(HEXAGON.C4_or_andn,QI_ftype_QIQIQI,3) +// +def int_hexagon_C4_or_andn : +Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON.C4.or_andn">; +// +// BUILTIN_INFO(HEXAGON.C4_or_and,QI_ftype_QIQIQI,3) +// +def int_hexagon_C4_or_and : +Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON.C4.or_and">; +// +// BUILTIN_INFO(HEXAGON.C4_or_orn,QI_ftype_QIQIQI,3) +// +def int_hexagon_C4_or_orn : +Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON.C4.or_orn">; +// +// BUILTIN_INFO(HEXAGON.C4_or_or,QI_ftype_QIQIQI,3) +// +def int_hexagon_C4_or_or : +Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON.C4.or_or">; +// +// BUILTIN_INFO(HEXAGON.S4_addaddi,SI_ftype_SISISI,3) +// +def int_hexagon_S4_addaddi : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S4.addaddi">; +// +// BUILTIN_INFO(HEXAGON.S4_subaddi,SI_ftype_SISISI,3) +// +def int_hexagon_S4_subaddi : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S4.subaddi">; +// +// BUILTIN_INFO(HEXAGON.S4_andnp,DI_ftype_DIDI,2) +// +def int_hexagon_S4_andnp : +Hexagon_di_didi_Intrinsic<"HEXAGON.S4.andnp">; +// +// BUILTIN_INFO(HEXAGON.S4_ornp,DI_ftype_DIDI,2) +// +def int_hexagon_S4_ornp : +Hexagon_di_didi_Intrinsic<"HEXAGON.S4.ornp">; +// +// BUILTIN_INFO(HEXAGON.M4_xor_xacc,DI_ftype_DIDIDI,3) +// +def int_hexagon_M4_xor_xacc : +Hexagon_di_dididi_Intrinsic<"HEXAGON.M4.xor_xacc">; +// +// BUILTIN_INFO(HEXAGON.M4_and_and,SI_ftype_SISISI,3) +// +def int_hexagon_M4_and_and : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M4.and_and">; +// +// BUILTIN_INFO(HEXAGON.M4_and_andn,SI_ftype_SISISI,3) +// +def int_hexagon_M4_and_andn : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M4.and_andn">; +// +// BUILTIN_INFO(HEXAGON.M4_and_or,SI_ftype_SISISI,3) +// +def int_hexagon_M4_and_or : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M4.and_or">; +// +// BUILTIN_INFO(HEXAGON.M4_and_xor,SI_ftype_SISISI,3) +// +def int_hexagon_M4_and_xor : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M4.and_xor">; +// +// BUILTIN_INFO(HEXAGON.M4_xor_and,SI_ftype_SISISI,3) +// +def int_hexagon_M4_xor_or : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M4.xor_or">; +// +// BUILTIN_INFO(HEXAGON.M4_xor_or,SI_ftype_SISISI,3) +// +def int_hexagon_M4_xor_and : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M4.xor_and">; +// +// BUILTIN_INFO(HEXAGON.M4_xor_andn,SI_ftype_SISISI,3) +// +def int_hexagon_M4_xor_andn : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M4.xor_andn">; +// +// BUILTIN_INFO(HEXAGON.M4_or_and,SI_ftype_SISISI,3) +// +def int_hexagon_M4_or_and : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M4.or_and">; +// +// BUILTIN_INFO(HEXAGON.M4_or_or,SI_ftype_SISISI,3) +// +def int_hexagon_M4_or_or : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M4.or_or">; +// +// BUILTIN_INFO(HEXAGON.M4_or_xor,SI_ftype_SISISI,3) +// +def int_hexagon_M4_or_xor : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M4.or_xor">; +// +// BUILTIN_INFO(HEXAGON.M4_or_andn,SI_ftype_SISISI,3) +// +def int_hexagon_M4_or_andn : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.M4.or_andn">; +// +// BUILTIN_INFO(HEXAGON.S4_or_andix,SI_ftype_SISISI,3) +// +def int_hexagon_S4_or_andix : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S4.or_andix">; +// +// BUILTIN_INFO(HEXAGON.S4_or_andi,SI_ftype_SISISI,3) +// +def int_hexagon_S4_or_andi : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S4.or_andi">; +// +// BUILTIN_INFO(HEXAGON.S4_or_ori,SI_ftype_SISISI,3) +// +def int_hexagon_S4_or_ori : +Hexagon_si_sisisi_Intrinsic<"HEXAGON.S4.or_ori">; +// +// BUILTIN_INFO(HEXAGON.A4_modwrapu,SI_ftype_SISI,2) +// +def int_hexagon_A4_modwrapu : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A4.modwrapu">; +// +// BUILTIN_INFO(HEXAGON.A4_cround_ri,SI_ftype_SISI,2) +// +def int_hexagon_A4_cround_ri : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A4.cround_ri">; +// +// BUILTIN_INFO(HEXAGON.A4_cround_rr,SI_ftype_SISI,2) +// +def int_hexagon_A4_cround_rr : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A4.cround_rr">; +// +// BUILTIN_INFO(HEXAGON.A4_round_ri,SI_ftype_SISI,2) +// +def int_hexagon_A4_round_ri : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A4.round_ri">; +// +// BUILTIN_INFO(HEXAGON.A4_round_rr,SI_ftype_SISI,2) +// +def int_hexagon_A4_round_rr : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A4.round_rr">; +// +// BUILTIN_INFO(HEXAGON.A4_round_ri_sat,SI_ftype_SISI,2) +// +def int_hexagon_A4_round_ri_sat : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A4.round_ri_sat">; +// +// BUILTIN_INFO(HEXAGON.A4_round_rr_sat,SI_ftype_SISI,2) +// +def int_hexagon_A4_round_rr_sat : +Hexagon_si_sisi_Intrinsic<"HEXAGON.A4.round_rr_sat">; diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h index 4627557f7f..d085c94f2a 100644 --- a/include/llvm/Support/MathExtras.h +++ b/include/llvm/Support/MathExtras.h @@ -51,6 +51,13 @@ inline bool isInt<32>(int64_t x) { return static_cast<int32_t>(x) == x; } +/// isShiftedInt<N,S> - Checks if a signed integer is an N bit number shifted +/// left by S. +template<unsigned N, unsigned S> +inline bool isShiftedInt(int64_t x) { + return isInt<N+S>(x) && (x % (1<<S) == 0); +} + /// isUInt - Checks if an unsigned integer fits into the given bit width. template<unsigned N> inline bool isUInt(uint64_t x) { @@ -70,6 +77,13 @@ inline bool isUInt<32>(uint64_t x) { return static_cast<uint32_t>(x) == x; } +/// isShiftedUInt<N,S> - Checks if a unsigned integer is an N bit number shifted +/// left by S. +template<unsigned N, unsigned S> +inline bool isShiftedUInt(uint64_t x) { + return isUInt<N+S>(x) && (x % (1<<S) == 0); +} + /// isUIntN - Checks if an unsigned integer fits into the given (dynamic) /// bit width. inline bool isUIntN(unsigned N, uint64_t x) { diff --git a/lib/Support/Triple.cpp b/lib/Support/Triple.cpp index ac4f005ab1..8f58e7029a 100644 --- a/lib/Support/Triple.cpp +++ b/lib/Support/Triple.cpp @@ -20,6 +20,7 @@ const char *Triple::getArchTypeName(ArchType Kind) { case arm: return "arm"; case cellspu: return "cellspu"; + case hexagon: return "hexagon"; case mips: return "mips"; case mipsel: return "mipsel"; case mips64: return "mips64"; @@ -59,6 +60,8 @@ const char *Triple::getArchTypePrefix(ArchType Kind) { case mblaze: return "mblaze"; + case hexagon: return "hexagon"; + case sparcv9: case sparc: return "sparc"; @@ -150,6 +153,8 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) { return ppc; if (Name == "mblaze") return mblaze; + if (Name == "hexagon") + return hexagon; if (Name == "sparc") return sparc; if (Name == "sparcv9") @@ -295,6 +300,8 @@ Triple::ArchType Triple::ParseArch(StringRef ArchName) { return mips64; else if (ArchName == "mips64el") return mips64el; + else if (ArchName == "hexagon") + return hexagon; else if (ArchName == "sparc") return sparc; else if (ArchName == "sparcv9") diff --git a/lib/Target/Hexagon/CMakeLists.txt b/lib/Target/Hexagon/CMakeLists.txt new file mode 100644 index 0000000000..898590aec0 --- /dev/null +++ b/lib/Target/Hexagon/CMakeLists.txt @@ -0,0 +1,43 @@ +set(LLVM_TARGET_DEFINITIONS Hexagon.td) + +tablegen(LLVM HexagonGenRegisterInfo.inc -gen-register-info) +tablegen(LLVM HexagonGenInstrInfo.inc -gen-instr-info) +tablegen(LLVM HexagonGenAsmWriter.inc -gen-asm-writer) +tablegen(LLVM HexagonGenDAGISel.inc -gen-dag-isel) +tablegen(LLVM HexagonGenCallingConv.inc -gen-callingconv) +tablegen(LLVM HexagonGenSubtargetInfo.inc -gen-subtarget) +tablegen(LLVM HexagonGenIntrinsics.inc -gen-tgt-intrinsic) +add_public_tablegen_target(HexagonCommonTableGen) + +add_llvm_target(HexagonCodeGen + HexagonAsmPrinter.cpp + HexagonCallingConvLower.cpp + HexagonCFGOptimizer.cpp + HexagonExpandPredSpillCode.cpp + HexagonFrameLowering.cpp + HexagonHardwareLoops.cpp + HexagonInstrInfo.cpp + HexagonISelDAGToDAG.cpp + HexagonISelLowering.cpp + HexagonMCAsmInfo.cpp + HexagonOptimizeSZExtends.cpp + HexagonRegisterInfo.cpp + HexagonRemoveSZExtArgs.cpp + HexagonSelectionDAGInfo.cpp + HexagonSplitTFRCondSets.cpp + HexagonSubtarget.cpp + HexagonTargetMachine.cpp + HexagonTargetObjectFile.cpp + ) + +add_llvm_library_dependencies(LLVMHexagonCodeGen + LLVMAsmPrinter + LLVMCodeGen + LLVMCore + LLVMHexagonInfo + LLVMSelectionDAG + LLVMSupport + LLVMTarget + ) + +add_subdirectory(TargetInfo) diff --git a/lib/Target/Hexagon/Hexagon.h b/lib/Target/Hexagon/Hexagon.h new file mode 100644 index 0000000000..ced3e9f846 --- /dev/null +++ b/lib/Target/Hexagon/Hexagon.h @@ -0,0 +1,68 @@ +//=-- Hexagon.h - Top-level interface for Hexagon representation --*- 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 the entry points for global functions defined in the LLVM +// Hexagon back-end. +// +//===----------------------------------------------------------------------===// + +#ifndef TARGET_Hexagon_H +#define TARGET_Hexagon_H + +#include <cassert> +#include "llvm/Target/TargetLowering.h" + +namespace llvm { + class FunctionPass; + class TargetMachine; + class HexagonTargetMachine; + class raw_ostream; + + FunctionPass *createHexagonISelDag(HexagonTargetMachine &TM); + FunctionPass *createHexagonDelaySlotFillerPass(TargetMachine &TM); + FunctionPass *createHexagonFPMoverPass(TargetMachine &TM); + FunctionPass *createHexagonRemoveExtendOps(HexagonTargetMachine &TM); + FunctionPass *createHexagonCFGOptimizer(HexagonTargetMachine &TM); + + FunctionPass* createHexagonSplitTFRCondSets(HexagonTargetMachine &TM); + FunctionPass* createHexagonExpandPredSpillCode(HexagonTargetMachine &TM); + + FunctionPass *createHexagonHardwareLoops(); + FunctionPass *createHexagonOptimizeSZExtends(); + FunctionPass *createHexagonFixupHwLoops(); + + extern Target TheHexagonTarget; + +} // end namespace llvm; + +// Defines symbolic names for Hexagon instructions and registers. +// This defines a mapping from register name to register number. +// + +#define GET_REGINFO_ENUM +#include "HexagonGenRegisterInfo.inc" + +#define GET_INSTRINFO_ENUM +#include "HexagonGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_ENUM +#include "HexagonGenSubtargetInfo.inc" + +#define Hexagon_POINTER_SIZE 4 + +#define Hexagon_PointerSize (Hexagon_POINTER_SIZE) +#define Hexagon_PointerSize_Bits (Hexagon_POINTER_SIZE * 8) +#define Hexagon_WordSize Hexagon_PointerSize +#define Hexagon_WordSize_Bits Hexagon_PointerSize_Bits + +// allocframe saves LR and FP on stack before allocating +// a new stack frame. This takes 8 bytes. +#define HEXAGON_LRFP_SIZE 8 + +#endif diff --git a/lib/Target/Hexagon/Hexagon.td b/lib/Target/Hexagon/Hexagon.td new file mode 100644 index 0000000000..72939e6f1f --- /dev/null +++ b/lib/Target/Hexagon/Hexagon.td @@ -0,0 +1,66 @@ +//===- Hexagon.td - Describe the Hexagon Target Machine ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Target-independent interfaces which we are implementing +//===----------------------------------------------------------------------===// + +include "llvm/Target/Target.td" + +//===----------------------------------------------------------------------===// +// Hexagon Subtarget features. +// + + +// Hexagon Archtectures +def ArchV2 : SubtargetFeature<"v2", "HexagonArchVersion", "V2", + "Hexagon v2">; +def ArchV3 : SubtargetFeature<"v3", "HexagonArchVersion", "V3", + "Hexagon v3">; +def ArchV4 : SubtargetFeature<"v4", "HexagonArchVersion", "V4", + "Hexagon v4">; + +//===----------------------------------------------------------------------===// +// Register File, Calling Conv, Instruction Descriptions +//===----------------------------------------------------------------------===// +include "HexagonSchedule.td" +include "HexagonRegisterInfo.td" +include "HexagonCallingConv.td" +include "HexagonInstrInfo.td" +include "HexagonIntrinsics.td" +include "HexagonIntrinsicsDerived.td" + + +def HexagonInstrInfo : InstrInfo { + // Define how we want to layout our target-specific information field. +} + +//===----------------------------------------------------------------------===// +// Hexagon processors supported. +//===----------------------------------------------------------------------===// + +class Proc<string Name, ProcessorItineraries Itin, + list<SubtargetFeature> Features> + : Processor<Name, Itin, Features>; + +def : Proc<"hexagonv2", HexagonItineraries, [ArchV2]>; +def : Proc<"hexagonv3", HexagonItineraries, [ArchV2, ArchV3]>; +def : Proc<"hexagonv4", HexagonItinerariesV4, [ArchV2, ArchV3, ArchV4]>; + +//===----------------------------------------------------------------------===// +// Declare the target which we are implementing +//===----------------------------------------------------------------------===// + +def Hexagon : Target { + // Pull in Instruction Info: + let InstructionSet = HexagonInstrInfo; +} diff --git a/lib/Target/Hexagon/HexagonAsmPrinter.cpp b/lib/Target/Hexagon/HexagonAsmPrinter.cpp new file mode 100644 index 0000000000..8f8e804024 --- /dev/null +++ b/lib/Target/Hexagon/HexagonAsmPrinter.cpp @@ -0,0 +1,555 @@ +//===-- HexagonAsmPrinter.cpp - Print machine instrs to Hexagon assembly ----=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a printer that converts from our internal representation +// of machine-dependent LLVM code to Hexagon assembly language. This printer is +// the output mechanism used by `llc'. +// +// Documentation at http://developer.apple.com/documentation/DeveloperTools/ +// Reference/Assembler/ASMIntroduction/chapter_1_section_1.html +// +//===----------------------------------------------------------------------===// + + +#define DEBUG_TYPE "asm-printer" +#include "Hexagon.h" +#include "HexagonTargetMachine.h" +#include "HexagonSubtarget.h" +#include "HexagonMachineFunctionInfo.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +static cl::opt<bool> AlignCalls( + "hexagon-align-calls", cl::Hidden, cl::init(true), + cl::desc("Insert falign after call instruction for Hexagon target")); + + +namespace { + class HexagonAsmPrinter : public AsmPrinter { + const HexagonSubtarget *Subtarget; + + public: + explicit HexagonAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) + : AsmPrinter(TM, Streamer) { + Subtarget = &TM.getSubtarget<HexagonSubtarget>(); + } + + virtual const char *getPassName() const { + return "Hexagon Assembly Printer"; + } + + /// printInstruction - This method is automatically generated by tablegen + /// from the instruction set description. This method returns true if the + /// machine instruction was sufficiently described to print it, otherwise it + void printInstruction(const MachineInstr *MI, raw_ostream &O); + virtual void EmitInstruction(const MachineInstr *MI); + + void printOp(const MachineOperand &MO, raw_ostream &O); + + /// printRegister - Print register according to target requirements. + /// + void printRegister(const MachineOperand &MO, bool R0AsZero, + raw_ostream &O) { + unsigned RegNo = MO.getReg(); + assert(TargetRegisterInfo::isPhysicalRegister(RegNo) && "Not physreg??"); + O << getRegisterName(RegNo); + } + + void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &OS) { + const MachineOperand &MO = MI->getOperand(OpNo); + if (MO.isReg()) { + printRegister(MO, false, OS); + } else if (MO.isImm()) { + OS << MO.getImm(); + } else { + printOp(MO, OS); + } + } + + + bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const; + + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &OS); + bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &OS); + + + void printHexagonImmOperand(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O) { + int value = MI->getOperand(OpNo).getImm(); + O << value; + } + + + void printHexagonNegImmOperand(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O) { + int value = MI->getOperand(OpNo).getImm(); + O << -value; + } + + void printHexagonMEMriOperand(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O) { + const MachineOperand &MO1 = MI->getOperand(OpNo); + const MachineOperand &MO2 = MI->getOperand(OpNo+1); + + O << getRegisterName(MO1.getReg()) + << " + #" + << (int) MO2.getImm(); + } + + + void printHexagonFrameIndexOperand(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O) { + const MachineOperand &MO1 = MI->getOperand(OpNo); + const MachineOperand &MO2 = MI->getOperand(OpNo+1); + + O << getRegisterName(MO1.getReg()) + << ", #" + << MO2.getImm(); + } + + void printBranchOperand(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O) { + // Branches can take an immediate operand. This is used by the branch + // selection pass to print $+8, an eight byte displacement from the PC. + if (MI->getOperand(OpNo).isImm()) { + O << "$+" << MI->getOperand(OpNo).getImm()*4; + } else { + printOp(MI->getOperand(OpNo), O); + } + } + + void printCallOperand(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O) { + } + + void printAbsAddrOperand(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O) { + } + + + void printSymbolHi(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { + O << "#HI("; + if (MI->getOperand(OpNo).isImm()) { + printHexagonImmOperand(MI, OpNo, O); + } else { + printOp(MI->getOperand(OpNo), O); + } + O << ")"; + } + + void printSymbolLo(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) { + O << "#HI("; + if (MI->getOperand(OpNo).isImm()) { + printHexagonImmOperand(MI, OpNo, O); + } else { + printOp(MI->getOperand(OpNo), O); + } + O << ")"; + } + + void printPredicateOperand(const MachineInstr *MI, unsigned OpNo, + raw_ostream &O); + + void printAddrModeBasePlusOffset(const MachineInstr *MI, int OpNo, + raw_ostream &O); + + void printGlobalOperand(const MachineInstr *MI, int OpNo, raw_ostream &O); + void printJumpTable(const MachineInstr *MI, int OpNo, raw_ostream &O); + + void EmitAlignment(unsigned NumBits, const GlobalValue *GV = 0) const; + + static const char *getRegisterName(unsigned RegNo); + }; + +} // end of anonymous namespace + +// Include the auto-generated portion of the assembly writer. +#include "HexagonGenAsmWriter.inc" + + +void HexagonAsmPrinter::EmitAlignment(unsigned NumBits, + const GlobalValue *GV) const { + + // For basic block level alignment, use falign. + if (!GV) { + OutStreamer.EmitRawText(StringRef("\t.falign")); + return; + } + + AsmPrinter::EmitAlignment(NumBits, GV); +} + +void HexagonAsmPrinter::printOp(const MachineOperand &MO, raw_ostream &O) { + switch (MO.getType()) { + case MachineOperand::MO_Immediate: + dbgs() << "printOp() does not handle immediate values\n"; + abort(); + return; + + case MachineOperand::MO_MachineBasicBlock: + O << *MO.getMBB()->getSymbol(); + return; + case MachineOperand::MO_JumpTableIndex: + O << *GetJTISymbol(MO.getIndex()); + // FIXME: PIC relocation model. + return; + case MachineOperand::MO_ConstantPoolIndex: + O << *GetCPISymbol(MO.getIndex()); + return; + case MachineOperand::MO_ExternalSymbol: + O << *GetExternalSymbolSymbol(MO.getSymbolName()); + return; + case MachineOperand::MO_GlobalAddress: { + // Computing the address of a global symbol, not calling it. + O << *Mang->getSymbol(MO.getGlobal()); + printOffset(MO.getOffset(), O); + return; + } + + default: + O << "<unknown operand type: " << MO.getType() << ">"; + return; + } +} + + +// +// isBlockOnlyReachableByFallthrough - We need to override this since the +// default AsmPrinter does not print labels for any basic block that +// is only reachable by a fall through. That works for all cases except +// for the case in which the basic block is reachable by a fall through but +// through an indirect from a jump table. In this case, the jump table +// will contain a label not defined by AsmPrinter. +// +bool HexagonAsmPrinter:: +isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const { + if (MBB->hasAddressTaken()) { + return false; + } + return AsmPrinter::isBlockOnlyReachableByFallthrough(MBB); +} + + +/// PrintAsmOperand - Print out an operand for an inline asm expression. +/// +bool HexagonAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, + const char *ExtraCode, + raw_ostream &OS) { + // Does this asm operand have a single letter operand modifier? + if (ExtraCode && ExtraCode[0]) { + if (ExtraCode[1] != 0) return true; // Unknown modifier. + + switch (ExtraCode[0]) { + default: return true; // Unknown modifier. + case 'c': // Don't print "$" before a global var name or constant. + // Hexagon never has a prefix. + printOperand(MI, OpNo, OS); + return false; + case 'L': // Write second word of DImode reference. + // Verify that this operand has two consecutive registers. + if (!MI->getOperand(OpNo).isReg() || + OpNo+1 == MI->getNumOperands() || + !MI->getOperand(OpNo+1).isReg()) + return true; + ++OpNo; // Return the high-part. + break; + case 'I': + // Write 'i' if an integer constant, otherwise nothing. Used to print + // addi vs add, etc. + if (MI->getOperand(OpNo).isImm()) + OS << "i"; + return false; + } + } + + printOperand(MI, OpNo, OS); + return false; +} + +bool HexagonAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, + unsigned OpNo, unsigned AsmVariant, + const char *ExtraCode, + raw_ostream &O) { + if (ExtraCode && ExtraCode[0]) + return true; // Unknown modifier. + + const MachineOperand &Base = MI->getOperand(OpNo); + const MachineOperand &Offset = MI->getOperand(OpNo+1); + + if (Base.isReg()) + printOperand(MI, OpNo, O); + else + assert(0 && "Unimplemented"); + + if (Offset.isImm()) { + if (Offset.getImm()) + O << " + #" << Offset.getImm(); + } + else + assert(0 && "Unimplemented"); + + return false; +} + +void HexagonAsmPrinter::printPredicateOperand(const MachineInstr *MI, + unsigned OpNo, + raw_ostream &O) { + assert(0 && "Unimplemented"); +} + + +/// printMachineInstruction -- Print out a single Hexagon MI in Darwin syntax to +/// the current output stream. +/// +void HexagonAsmPrinter::EmitInstruction(const MachineInstr *MI) { + SmallString<128> Str; + raw_svector_ostream O(Str); + + const MachineFunction* MF = MI->getParent()->getParent(); + const HexagonMachineFunctionInfo* MFI = + (const HexagonMachineFunctionInfo*) + MF->getInfo<HexagonMachineFunctionInfo>(); + + + + // Print a brace for the beginning of the packet. + if (MFI->isStartPacket(MI)) { + O << "\t{" << '\n'; + } + + DEBUG( O << "// MI = " << *MI << '\n';); + + // Indent + O << "\t"; + + + if (MI->getOpcode() == Hexagon::ENDLOOP0) { + if (MFI->isEndPacket(MI) && MFI->isStartPacket(MI)) { + O << "\t{ nop }"; + } else { + O << "}"; + } + printInstruction(MI, O); + } else if (MI->getOpcode() == Hexagon::STriwt) { + // + // Handle truncated store on Hexagon. + // + O << "\tmemw("; + printHexagonMEMriOperand(MI, 0, O); + + O << ") = "; + unsigned SubRegNum = + TM.getRegisterInfo()->getSubReg(MI->getOperand(2) + .getReg(), Hexagon::subreg_loreg); + const char *SubRegName = getRegisterName(SubRegNum); + O << SubRegName << '\n'; + } else if (MI->getOpcode() == Hexagon::MPYI_rin) { + // Handle multipy with -ve constant on Hexagon: + // "$dst =- mpyi($src1, #$src2)" + printOperand(MI, 0, O); + O << " =- mpyi("; + printOperand(MI, 1, O); + O << ", #"; + printHexagonNegImmOperand(MI, 2, O); + O << ")"; + } else if (MI->getOpcode() == Hexagon::MEMw_ADDSUBi_indexed_MEM_V4) { + // + // Handle memw(Rs+u6:2) [+-]= #U5 + // + O << "\tmemw("; printHexagonMEMriOperand(MI, 0, O); O << ") "; + int addend = MI->getOperand(2).getImm(); + if (addend < 0) + O << "-= " << "#" << -addend << '\n'; + else + O << "+= " << "#" << addend << '\n'; + } else if (MI->getOpcode() == Hexagon::MEMw_ADDSUBi_MEM_V4) { + // + // Handle memw(Rs+u6:2) [+-]= #U5 + // + O << "\tmemw("; printHexagonMEMriOperand(MI, 0, O); O << ") "; + int addend = MI->getOperand(2).getImm(); + if (addend < 0) + O << "-= " << "#" << -addend << '\n'; + else + O << "+= " << "#" << addend << '\n'; + } else if (MI->getOpcode() == Hexagon::MEMh_ADDSUBi_indexed_MEM_V4) { + // + // Handle memh(Rs+u6:1) [+-]= #U5 + // + O << "\tmemh("; printHexagonMEMriOperand(MI, 0, O); O << ") "; + int addend = MI->getOperand(2).getImm(); + if (addend < 0) + O << "-= " << "#" << -addend << '\n'; + else + O << "+= " << "#" << addend << '\n'; + } else if (MI->getOpcode() == Hexagon::MEMh_ADDSUBi_MEM_V4) { + // + // Handle memh(Rs+u6:1) [+-]= #U5 + // + O << "\tmemh("; printHexagonMEMriOperand(MI, 0, O); O << ") "; + int addend = MI->getOperand(2).getImm(); + if (addend < 0) + O << "-= " << "#" << -addend << '\n'; + else + O << "+= " << "#" << addend << '\n'; + } else if (MI->getOpcode() == Hexagon::MEMb_ADDSUBi_indexed_MEM_V4) { + // + // Handle memb(Rs+u6:1) [+-]= #U5 + // + O << "\tmemb("; printHexagonMEMriOperand(MI, 0, O); O << ") "; + int addend = MI->getOperand(2).getImm(); + if (addend < 0) + O << "-= " << "#" << -addend << '\n'; + else + O << "+= " << "#" << addend << '\n'; + } else if (MI->getOpcode() == Hexagon::MEMb_ADDSUBi_MEM_V4) { + // + // Handle memb(Rs+u6:1) [+-]= #U5 + // + O << "\tmemb("; printHexagonMEMriOperand(MI, 0, O); O << ") "; + int addend = MI->getOperand(2).getImm(); + if (addend < 0) + O << "-= " << "#" << -addend << '\n'; + else + O << "+= " << "#" << addend << '\n'; + } else if (MI->getOpcode() == Hexagon::CMPbGTri_V4) { + // + // Handle Pd=cmpb.gt(Rs,#s8) + // + O << "\t"; + printRegister(MI->getOperand(0), false, O); + O << " = cmpb.gt("; + printRegister(MI->getOperand(1), false, O); + O << ", "; + int val = MI->getOperand(2).getImm() >> 24; + O << "#" << val << ")" << '\n'; + } else if (MI->getOpcode() == Hexagon::CMPhEQri_V4) { + // + // Handle Pd=cmph.eq(Rs,#8) + // + O << "\t"; + printRegister(MI->getOperand(0), false, O); + O << " = cmph.eq("; + printRegister(MI->getOperand(1), false, O); + O << ", "; + int val = MI->getOperand(2).getImm(); + assert((((0 <= val) && (val <= 127)) || + ((65408 <= val) && (val <= 65535))) && + "Not in correct range!"); + if (val >= 65408) val -= 65536; + O << "#" << val << ")" << '\n'; + } else if (MI->getOpcode() == Hexagon::CMPhGTri_V4) { + // + // Handle Pd=cmph.gt(Rs,#8) + // + O << "\t"; + printRegister(MI->getOperand(0), false, O); + O << " = cmph.gt("; + printRegister(MI->getOperand(1), false, O); + O << ", "; + int val = MI->getOperand(2).getImm() >> 16; + O << "#" << val << ")" << '\n'; + } else { + printInstruction(MI, O); + } + + // Print a brace for the end of the packet. + if (MFI->isEndPacket(MI) && MI->getOpcode() != Hexagon::ENDLOOP0) { + O << "\n\t}" << '\n'; + } + + if (AlignCalls && MI->getDesc().isCall()) { + O << "\n\t.falign" << "\n"; + } + + OutStreamer.EmitRawText(O.str()); + return; +} + +/// PrintUnmangledNameSafely - Print out the printable characters in the name. +/// Don't print things like \n or \0. +// static void PrintUnmangledNameSafely(const Value *V, raw_ostream &OS) { +// for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen(); +// Name != E; ++Name) +// if (isprint(*Name)) +// OS << *Name; +// } + + +void HexagonAsmPrinter::printAddrModeBasePlusOffset(const MachineInstr *MI, + int OpNo, raw_ostream &O) { + const MachineOperand &MO1 = MI->getOperand(OpNo); + const MachineOperand &MO2 = MI->getOperand(OpNo+1); + + O << getRegisterName(MO1.getReg()) + << " + #" + << MO2.getImm(); +} + + +void HexagonAsmPrinter::printGlobalOperand(const MachineInstr *MI, int OpNo, + raw_ostream &O) { + const MachineOperand &MO = MI->getOperand(OpNo); + assert( (MO.getType() == MachineOperand::MO_GlobalAddress) && + "Expecting global address"); + + O << *Mang->getSymbol(MO.getGlobal()); + if (MO.getOffset() != 0) { + O << " + "; + O << MO.getOffset(); + } +} + +void HexagonAsmPrinter::printJumpTable(const MachineInstr *MI, int OpNo, + raw_ostream &O) { + const MachineOperand &MO = MI->getOperand(OpNo); + assert( (MO.getType() == MachineOperand::MO_JumpTableIndex) && + "Expecting jump table index"); + + // Hexagon_TODO: Do we need name mangling? + O << *GetJTISymbol(MO.getIndex()); +} + +extern "C" void LLVMInitializeHexagonAsmPrinter() { + RegisterAsmPrinter<HexagonAsmPrinter> X(TheHexagonTarget); +} diff --git a/lib/Target/Hexagon/HexagonCFGOptimizer.cpp b/lib/Target/Hexagon/HexagonCFGOptimizer.cpp new file mode 100644 index 0000000000..38000e7806 --- /dev/null +++ b/lib/Target/Hexagon/HexagonCFGOptimizer.cpp @@ -0,0 +1,240 @@ +//===---- HexagonCFGOptimizer.cpp - CFG optimizations ---------------------===// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +#define DEBUG_TYPE "hexagon_cfg" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "HexagonTargetMachine.h" +#include "HexagonSubtarget.h" +#include "HexagonMachineFunctionInfo.h" +#include <iostream> + +#include "llvm/Support/CommandLine.h" + +using namespace llvm; + +namespace { + +class HexagonCFGOptimizer : public MachineFunctionPass { + +private: + HexagonTargetMachine& QTM; + const HexagonSubtarget &QST; + + void InvertAndChangeJumpTarget(MachineInstr*, MachineBasicBlock*); + + public: + static char ID; + HexagonCFGOptimizer(HexagonTargetMachine& TM) : MachineFunctionPass(ID), + QTM(TM), + QST(*TM.getSubtargetImpl()) {} + + const char *getPassName() const { + return "Hexagon CFG Optimizer"; + } + bool runOnMachineFunction(MachineFunction &Fn); +}; + + +char HexagonCFGOptimizer::ID = 0; + +static bool IsConditionalBranch(int Opc) { + return (Opc == Hexagon::JMP_Pred) || (Opc == Hexagon::JMP_PredNot) + || (Opc == Hexagon::JMP_PredPt) || (Opc == Hexagon::JMP_PredNotPt); +} + + +static bool IsUnconditionalJump(int Opc) { + return (Opc == Hexagon::JMP); +} + + +void +HexagonCFGOptimizer::InvertAndChangeJumpTarget(MachineInstr* MI, + MachineBasicBlock* NewTarget) { + const HexagonInstrInfo *QII = QTM.getInstrInfo(); + int NewOpcode = 0; + switch(MI->getOpcode()) { + case Hexagon::JMP_Pred: + NewOpcode = Hexagon::JMP_PredNot; + break; + + case Hexagon::JMP_PredNot: + NewOpcode = Hexagon::JMP_Pred; + break; + + case Hexagon::JMP_PredPt: + NewOpcode = Hexagon::JMP_PredNotPt; + break; + + case Hexagon::JMP_PredNotPt: + NewOpcode = Hexagon::JMP_PredPt; + break; + + default: + assert(0 && "Cannot handle this case"); + } + + MI->setDesc(QII->get(NewOpcode)); + MI->getOperand(1).setMBB(NewTarget); +} + + +bool HexagonCFGOptimizer::runOnMachineFunction(MachineFunction &Fn) { + + // Loop over all of the basic blocks. + for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end(); + MBBb != MBBe; ++MBBb) { + MachineBasicBlock* MBB = MBBb; + + // Traverse the basic block. + MachineBasicBlock::iterator MII = MBB->getFirstTerminator(); + if (MII != MBB->end()) { + MachineInstr *MI = MII; + int Opc = MI->getOpcode(); + if (IsConditionalBranch(Opc)) { + + // + // (Case 1) Transform the code if the following condition occurs: + // BB1: if (p0) jump BB3 + // ...falls-through to BB2 ... + // BB2: jump BB4 + // ...next block in layout is BB3... + // BB3: ... + // + // Transform this to: + // BB1: if (!p0) jump BB4 + // Remove BB2 + // BB3: ... + // + // (Case 2) A variation occurs when BB3 contains a JMP to BB4: + // BB1: if (p0) jump BB3 + // ...falls-through to BB2 ... + // BB2: jump BB4 + // ...other basic blocks ... + // BB4: + // ...not a fall-thru + // BB3: ... + // jump BB4 + // + // Transform this to: + // BB1: if (!p0) jump BB4 + // Remove BB2 + // BB3: ... + // BB4: ... + // + unsigned NumSuccs = MBB->succ_size(); + MachineBasicBlock::succ_iterator SI = MBB->succ_begin(); + MachineBasicBlock* FirstSucc = *SI; + MachineBasicBlock* SecondSucc = *(++SI); + MachineBasicBlock* LayoutSucc = NULL; + MachineBasicBlock* JumpAroundTarget = NULL; + + if (MBB->isLayoutSuccessor(FirstSucc)) { + LayoutSucc = FirstSucc; + JumpAroundTarget = SecondSucc; + } else if (MBB->isLayoutSuccessor(SecondSucc)) { + LayoutSucc = SecondSucc; + JumpAroundTarget = FirstSucc; + } else { + // Odd case...cannot handle. + } + + // The target of the unconditional branch must be JumpAroundTarget. + // TODO: If not, we should not invert the unconditional branch. + MachineBasicBlock* CondBranchTarget = NULL; + if ((MI->getOpcode() == Hexagon::JMP_Pred) || + (MI->getOpcode() == Hexagon::JMP_PredNot)) { + CondBranchTarget = MI->getOperand(1).getMBB(); + } + + if (!LayoutSucc || (CondBranchTarget != JumpAroundTarget)) { + continue; + } + + if ((NumSuccs == 2) && LayoutSucc && (LayoutSucc->pred_size() == 1)) { + + // Ensure that BB2 has one instruction -- an unconditional jump. + if ((LayoutSucc->size() == 1) && + IsUnconditionalJump(LayoutSucc->front().getOpcode())) { + MachineBasicBlock* UncondTarget = + LayoutSucc->front().getOperand(0).getMBB(); + // Check if the layout successor of BB2 is BB3. + bool case1 = LayoutSucc->isLayoutSuccessor(JumpAroundTarget); + bool case2 = JumpAroundTarget->isSuccessor(UncondTarget) && + JumpAroundTarget->size() >= 1 && + IsUnconditionalJump(JumpAroundTarget->back().getOpcode()) && + JumpAroundTarget->pred_size() == 1 && + JumpAroundTarget->succ_size() == 1; + + if (case1 || case2) { + InvertAndChangeJumpTarget(MI, UncondTarget); + MBB->removeSuccessor(JumpAroundTarget); + MBB->addSuccessor(UncondTarget); + + // Remove the unconditional branch in LayoutSucc. + LayoutSucc->erase(LayoutSucc->begin()); + LayoutSucc->removeSuccessor(UncondTarget); + LayoutSucc->addSuccessor(JumpAroundTarget); + + // This code performs the conversion for case 2, which moves + // the block to the fall-thru case (BB3 in the code above). + if (case2 && !case1) { + JumpAroundTarget->moveAfter(LayoutSucc); + // only move a block if it doesn't have a fall-thru. otherwise + // the CFG will be incorrect. + if (!UncondTarget->canFallThrough()) { + UncondTarget->moveAfter(JumpAroundTarget); + } + } + + // + // Correct live-in information. Is used by post-RA scheduler + // The live-in to LayoutSucc is now all values live-in to + // JumpAroundTarget. + // + std::vector<unsigned> OrigLiveIn(LayoutSucc->livein_begin(), + LayoutSucc->livein_end()); + std::vector<unsigned> NewLiveIn(JumpAroundTarget->livein_begin(), + JumpAroundTarget->livein_end()); + for (unsigned i = 0; i < OrigLiveIn.size(); ++i) { + LayoutSucc->removeLiveIn(OrigLiveIn[i]); + } + for (unsigned i = 0; i < NewLiveIn.size(); ++i) { + LayoutSucc->addLiveIn(NewLiveIn[i]); + } + } + } + } + } + } + } + return true; +} +} + + +//===----------------------------------------------------------------------===// +// Public Constructor Functions +//===----------------------------------------------------------------------===// + +FunctionPass *llvm::createHexagonCFGOptimizer(HexagonTargetMachine &TM) { + return new HexagonCFGOptimizer(TM); +} diff --git a/lib/Target/Hexagon/HexagonCallingConv.td b/lib/Target/Hexagon/HexagonCallingConv.td new file mode 100644 index 0000000000..bd9608bdb0 --- /dev/null +++ b/lib/Target/Hexagon/HexagonCallingConv.td @@ -0,0 +1,35 @@ +//===- HexagonCallingConv.td - Calling Conventions Hexagon -*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This describes the calling conventions for the Hexagon architectures. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Return Value Calling Conventions +//===----------------------------------------------------------------------===// + +// Hexagon 32-bit C return-value convention. +def RetCC_Hexagon32 : CallingConv<[ + CCIfType<[i32], CCAssignToReg<[R0, R1, R2, R3, R4, R5]>>, + CCIfType<[i64], CCAssignToReg<[D0, D1, D2]>>, + + // Alternatively, they are assigned to the stack in 4-byte aligned units. + CCAssignToStack<4, 4> +]>; + +// Hexagon 32-bit C Calling convention. +def CC_Hexagon32 : CallingConv<[ + // All arguments get passed in integer registers if there is space. + CCIfType<[i32, i16, i8], CCAssignToReg<[R0, R1, R2, R3, R4, R5]>>, + CCIfType<[i64], CCAssignToReg<[D0, D1, D2]>>, + + // Alternatively, they are assigned to the stack in 4-byte aligned units. + CCAssignToStack<4, 4> +]>; diff --git a/lib/Target/Hexagon/HexagonCallingConvLower.cpp b/lib/Target/Hexagon/HexagonCallingConvLower.cpp new file mode 100644 index 0000000000..2e51dbf51c --- /dev/null +++ b/lib/Target/Hexagon/HexagonCallingConvLower.cpp @@ -0,0 +1,207 @@ +//===-- llvm/CallingConvLower.cpp - Calling Convention lowering -----------===// +// +// 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 Hexagon_CCState class, used for lowering and +// implementing calling conventions. Adapted from the machine independent +// version of the class (CCState) but this handles calls to varargs functions +// +//===----------------------------------------------------------------------===// + +#include "HexagonCallingConvLower.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "Hexagon.h" +using namespace llvm; + +Hexagon_CCState::Hexagon_CCState(CallingConv::ID CC, bool isVarArg, + const TargetMachine &tm, + SmallVector<CCValAssign, 16> &locs, + LLVMContext &c) + : CallingConv(CC), IsVarArg(isVarArg), TM(tm), + TRI(*TM.getRegisterInfo()), Locs(locs), Context(c) { + // No stack is used. + StackOffset = 0; + + UsedRegs.resize((TRI.getNumRegs()+31)/32); +} + +// HandleByVal - Allocate a stack slot large enough to pass an argument by +// value. The size and alignment information of the argument is encoded in its +// parameter attribute. +void Hexagon_CCState::HandleByVal(unsigned ValNo, EVT ValVT, + EVT LocVT, CCValAssign::LocInfo LocInfo, + int MinSize, int MinAlign, + ISD::ArgFlagsTy ArgFlags) { + unsigned Align = ArgFlags.getByValAlign(); + unsigned Size = ArgFlags.getByValSize(); + if (MinSize > (int)Size) + Size = MinSize; + if (MinAlign > (int)Align) + Align = MinAlign; + unsigned Offset = AllocateStack(Size, Align); + + addLoc(CCValAssign::getMem(ValNo, ValVT.getSimpleVT(), Offset, + LocVT.getSimpleVT(), LocInfo)); +} + +/// MarkAllocated - Mark a register and all of its aliases as allocated. +void Hexagon_CCState::MarkAllocated(unsigned Reg) { + UsedRegs[Reg/32] |= 1 << (Reg&31); + + if (const unsigned *RegAliases = TRI.getAliasSet(Reg)) + for (; (Reg = *RegAliases); ++RegAliases) + UsedRegs[Reg/32] |= 1 << (Reg&31); +} + +/// AnalyzeFormalArguments - Analyze an ISD::FORMAL_ARGUMENTS node, +/// incorporating info about the formals into this state. +void +Hexagon_CCState::AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> + &Ins, + Hexagon_CCAssignFn Fn, + unsigned SretValueInRegs) { + unsigned NumArgs = Ins.size(); + unsigned i = 0; + + // If the function returns a small struct in registers, skip + // over the first (dummy) argument. + if (SretValueInRegs != 0) { + ++i; + } + + + for (; i != NumArgs; ++i) { + EVT ArgVT = Ins[i].VT; + ISD::ArgFlagsTy ArgFlags = Ins[i].Flags; + if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this, 0, 0, false)) { + dbgs() << "Formal argument #" << i << " has unhandled type " + << ArgVT.getEVTString() << "\n"; + abort(); + } + } +} + +/// AnalyzeReturn - Analyze the returned values of an ISD::RET node, +/// incorporating info about the result values into this state. +void +Hexagon_CCState::AnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs, + Hexagon_CCAssignFn Fn, + unsigned SretValueInRegs) { + + // For Hexagon, Return small structures in registers. + if (SretValueInRegs != 0) { + if (SretValueInRegs <= 32) { + unsigned Reg = Hexagon::R0; + addLoc(CCValAssign::getReg(0, MVT::i32, Reg, MVT::i32, + CCValAssign::Full)); + return; + } + if (SretValueInRegs <= 64) { + unsigned Reg = Hexagon::D0; + addLoc(CCValAssign::getReg(0, MVT::i64, Reg, MVT::i64, + CCValAssign::Full)); + return; + } + } + + + // Determine which register each value should be copied into. + for (unsigned i = 0, e = Outs.size(); i != e; ++i) { + EVT VT = Outs[i].VT; + ISD::ArgFlagsTy ArgFlags = Outs[i].Flags; + if (Fn(i, VT, VT, CCValAssign::Full, ArgFlags, *this, -1, -1, false)){ + dbgs() << "Return operand #" << i << " has unhandled type " + << VT.getEVTString() << "\n"; + abort(); + } + } +} + + +/// AnalyzeCallOperands - Analyze an ISD::CALL node, incorporating info +/// about the passed values into this state. +void +Hexagon_CCState::AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> + &Outs, + Hexagon_CCAssignFn Fn, + int NonVarArgsParams, + unsigned SretValueSize) { + unsigned NumOps = Outs.size(); + + unsigned i = 0; + // If the called function returns a small struct in registers, skip + // the first actual parameter. We do not want to pass a pointer to + // the stack location. + if (SretValueSize != 0) { + ++i; + } + + for (; i != NumOps; ++i) { + EVT ArgVT = Outs[i].VT; + ISD::ArgFlagsTy ArgFlags = Outs[i].Flags; + if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this, + NonVarArgsParams, i+1, false)) { + dbgs() << "Call operand #" << i << " has unhandled type " + << ArgVT.getEVTString() << "\n"; + abort(); + } + } +} + +/// AnalyzeCallOperands - Same as above except it takes vectors of types +/// and argument flags. +void +Hexagon_CCState::AnalyzeCallOperands(SmallVectorImpl<EVT> &ArgVTs, + SmallVectorImpl<ISD::ArgFlagsTy> &Flags, + Hexagon_CCAssignFn Fn) { + unsigned NumOps = ArgVTs.size(); + for (unsigned i = 0; i != NumOps; ++i) { + EVT ArgVT = ArgVTs[i]; + ISD::ArgFlagsTy ArgFlags = Flags[i]; + if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this, -1, -1, + false)) { + dbgs() << "Call operand #" << i << " has unhandled type " + << ArgVT.getEVTString() << "\n"; + abort(); + } + } +} + +/// AnalyzeCallResult - Analyze the return values of an ISD::CALL node, +/// incorporating info about the passed values into this state. +void +Hexagon_CCState::AnalyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins, + Hexagon_CCAssignFn Fn, + unsigned SretValueInRegs) { + + for (unsigned i = 0, e = Ins.size(); i != e; ++i) { + EVT VT = Ins[i].VT; + ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy(); + if (Fn(i, VT, VT, CCValAssign::Full, Flags, *this, -1, -1, false)) { + dbgs() << "Call result #" << i << " has unhandled type " + << VT.getEVTString() << "\n"; + abort(); + } + } +} + +/// AnalyzeCallResult - Same as above except it's specialized for calls which +/// produce a single value. +void Hexagon_CCState::AnalyzeCallResult(EVT VT, Hexagon_CCAssignFn Fn) { + if (Fn(0, VT, VT, CCValAssign::Full, ISD::ArgFlagsTy(), *this, -1, -1, + false)) { + dbgs() << "Call result has unhandled type " + << VT.getEVTString() << "\n"; + abort(); + } +} diff --git a/lib/Target/Hexagon/HexagonCallingConvLower.h b/lib/Target/Hexagon/HexagonCallingConvLower.h new file mode 100644 index 0000000000..1f601e87ad --- /dev/null +++ b/lib/Target/Hexagon/HexagonCallingConvLower.h @@ -0,0 +1,189 @@ +//===-- HexagonCallingConvLower.h - Calling Conventions ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the Hexagon_CCState class, used for lowering +// and implementing calling conventions. Adapted from the target independent +// version but this handles calls to varargs functions +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_Hexagon_CODEGEN_CALLINGCONVLOWER_H +#define LLVM_Hexagon_CODEGEN_CALLINGCONVLOWER_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/CodeGen/CallingConvLower.h" + +// +// Need to handle varargs. +// +namespace llvm { + class TargetRegisterInfo; + class TargetMachine; + class Hexagon_CCState; + class SDNode; + + +/// Hexagon_CCAssignFn - This function assigns a location for Val, updating +/// State to reflect the change. +typedef bool Hexagon_CCAssignFn(unsigned ValNo, EVT ValVT, + EVT LocVT, CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, Hexagon_CCState &State, + int NonVarArgsParams, + int CurrentParam, + bool ForceMem); + + +/// CCState - This class holds information needed while lowering arguments and +/// return values. It captures which registers are already assigned and which +/// stack slots are used. It provides accessors to allocate these values. +class Hexagon_CCState { + CallingConv::ID CallingConv; + bool IsVarArg; + const TargetMachine &TM; + const TargetRegisterInfo &TRI; + SmallVector<CCValAssign, 16> &Locs; + LLVMContext &Context; + + unsigned StackOffset; + SmallVector<uint32_t, 16> UsedRegs; +public: + Hexagon_CCState(CallingConv::ID CC, bool isVarArg, const TargetMachine &TM, + SmallVector<CCValAssign, 16> &locs, LLVMContext &c); + + void addLoc(const CCValAssign &V) { + Locs.push_back(V); + } + + LLVMContext &getContext() const { return Context; } + const TargetMachine &getTarget() const { return TM; } + unsigned getCallingConv() const { return CallingConv; } + bool isVarArg() const { return IsVarArg; } + + unsigned getNextStackOffset() const { return StackOffset; } + + /// isAllocated - Return true if the specified register (or an alias) is + /// allocated. + bool isAllocated(unsigned Reg) const { + return UsedRegs[Reg/32] & (1 << (Reg&31)); + } + + /// AnalyzeFormalArguments - Analyze an ISD::FORMAL_ARGUMENTS node, + /// incorporating info about the formals into this state. + void AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins, + Hexagon_CCAssignFn Fn, unsigned SretValueInRegs); + + /// AnalyzeReturn - Analyze the returned values of an ISD::RET node, + /// incorporating info about the result values into this state. + void AnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs, + Hexagon_CCAssignFn Fn, unsigned SretValueInRegs); + + /// AnalyzeCallOperands - Analyze an ISD::CALL node, incorporating info + /// about the passed values into this state. + void AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs, + Hexagon_CCAssignFn Fn, int NonVarArgsParams, + unsigned SretValueSize); + + /// AnalyzeCallOperands - Same as above except it takes vectors of types + /// and argument flags. + void AnalyzeCallOperands(SmallVectorImpl<EVT> &ArgVTs, + SmallVectorImpl<ISD::ArgFlagsTy> &Flags, + Hexagon_CCAssignFn Fn); + + /// AnalyzeCallResult - Analyze the return values of an ISD::CALL node, + /// incorporating info about the passed values into this state. + void AnalyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins, + Hexagon_CCAssignFn Fn, unsigned SretValueInRegs); + + /// AnalyzeCallResult - Same as above except it's specialized for calls which + /// produce a single value. + void AnalyzeCallResult(EVT VT, Hexagon_CCAssignFn Fn); + + /// getFirstUnallocated - Return the first unallocated register in the set, or + /// NumRegs if they are all allocated. + unsigned getFirstUnallocated(const unsigned *Regs, unsigned NumRegs) const { + for (unsigned i = 0; i != NumRegs; ++i) + if (!isAllocated(Regs[i])) + return i; + return NumRegs; + } + + /// AllocateReg - Attempt to allocate one register. If it is not available, + /// return zero. Otherwise, return the register, marking it and any aliases + /// as allocated. + unsigned AllocateReg(unsigned Reg) { + if (isAllocated(Reg)) return 0; + MarkAllocated(Reg); + return Reg; + } + + /// Version of AllocateReg with extra register to be shadowed. + unsigned AllocateReg(unsigned Reg, unsigned ShadowReg) { + if (isAllocated(Reg)) return 0; + MarkAllocated(Reg); + MarkAllocated(ShadowReg); + return Reg; + } + + /// AllocateReg - Attempt to allocate one of the specified registers. If none + /// are available, return zero. Otherwise, return the first one available, + /// marking it and any aliases as allocated. + unsigned AllocateReg(const unsigned *Regs, unsigned NumRegs) { + unsigned FirstUnalloc = getFirstUnallocated(Regs, NumRegs); + if (FirstUnalloc == NumRegs) + return 0; // Didn't find the reg. + + // Mark the register and any aliases as allocated. + unsigned Reg = Regs[FirstUnalloc]; + MarkAllocated(Reg); + return Reg; + } + + /// Version of AllocateReg with list of registers to be shadowed. + unsigned AllocateReg(const unsigned *Regs, const unsigned *ShadowRegs, + unsigned NumRegs) { + unsigned FirstUnalloc = getFirstUnallocated(Regs, NumRegs); + if (FirstUnalloc == NumRegs) + return 0; // Didn't find the reg. + + // Mark the register and any aliases as allocated. + unsigned Reg = Regs[FirstUnalloc], ShadowReg = ShadowRegs[FirstUnalloc]; + MarkAllocated(Reg); + MarkAllocated(ShadowReg); + return Reg; + } + + /// AllocateStack - Allocate a chunk of stack space with the specified size + /// and alignment. + unsigned AllocateStack(unsigned Size, unsigned Align) { + assert(Align && ((Align-1) & Align) == 0); // Align is power of 2. + StackOffset = ((StackOffset + Align-1) & ~(Align-1)); + unsigned Result = StackOffset; + StackOffset += Size; + return Result; + } + + // HandleByVal - Allocate a stack slot large enough to pass an argument by + // value. The size and alignment information of the argument is encoded in its + // parameter attribute. + void HandleByVal(unsigned ValNo, EVT ValVT, + EVT LocVT, CCValAssign::LocInfo LocInfo, + int MinSize, int MinAlign, ISD::ArgFlagsTy ArgFlags); + +private: + /// MarkAllocated - Mark a register and all of its aliases as allocated. + void MarkAllocated(unsigned Reg); +}; + + + +} // end namespace llvm + +#endif diff --git a/lib/Target/Hexagon/HexagonExpandPredSpillCode.cpp b/lib/Target/Hexagon/HexagonExpandPredSpillCode.cpp new file mode 100644 index 0000000000..cb73ae0039 --- /dev/null +++ b/lib/Target/Hexagon/HexagonExpandPredSpillCode.cpp @@ -0,0 +1,184 @@ +//===--- HexagonExpandPredSpillCode.cpp - Expand Predicate Spill Code ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===//// +// The Hexagon processor has no instructions that load or store predicate +// registers directly. So, when these registers must be spilled a general +// purpose register must be found and the value copied to/from it from/to +// the predicate register. This code currently does not use the register +// scavenger mechanism available in the allocator. There are two registers +// reserved to allow spilling/restoring predicate registers. One is used to +// hold the predicate value. The other is used when stack frame offsets are +// too large. +// +//===----------------------------------------------------------------------===// + + +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/LatencyPriorityQueue.h" +#include "llvm/CodeGen/SchedulerRegistry.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/ScheduleHazardRecognizer.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "HexagonTargetMachine.h" +#include "HexagonSubtarget.h" +#include "HexagonMachineFunctionInfo.h" +#include <map> +#include <iostream> + +#include "llvm/Support/CommandLine.h" + + +using namespace llvm; + + +namespace { + +class HexagonExpandPredSpillCode : public MachineFunctionPass { + HexagonTargetMachine& QTM; + const HexagonSubtarget &QST; + + public: + static char ID; + HexagonExpandPredSpillCode(HexagonTargetMachine& TM) : + MachineFunctionPass(ID), QTM(TM), QST(*TM.getSubtargetImpl()) {} + + const char *getPassName() const { + return "Hexagon Expand Predicate Spill Code"; + } + bool runOnMachineFunction(MachineFunction &Fn); +}; + + +char HexagonExpandPredSpillCode::ID = 0; + + +bool HexagonExpandPredSpillCode::runOnMachineFunction(MachineFunction &Fn) { + + const HexagonInstrInfo *TII = QTM.getInstrInfo(); + const HexagonRegisterInfo *RegInfo = QTM.getRegisterInfo(); + + // Loop over all of the basic blocks. + for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end(); + MBBb != MBBe; ++MBBb) { + MachineBasicBlock* MBB = MBBb; + // Traverse the basic block. + for (MachineBasicBlock::iterator MII = MBB->begin(); MII != MBB->end(); + ++MII) { + MachineInstr *MI = MII; + int Opc = MI->getOpcode(); + if (Opc == Hexagon::STriw_pred) { + // STriw_pred [R30], ofst, SrcReg; + unsigned FP = MI->getOperand(0).getReg(); + assert(FP == RegInfo->getFrameRegister() && + "Not a Frame Pointer, Nor a Spill Slot"); + assert(MI->getOperand(1).isImm() && "Not an offset"); + int Offset = MI->getOperand(1).getImm(); + int SrcReg = MI->getOperand(2).getReg(); + assert(Hexagon::PredRegsRegClass.contains(SrcReg) && + "Not a predicate register"); + if (!TII->isValidOffset(Hexagon::STriw, Offset)) { + if (!TII->isValidOffset(Hexagon::ADD_ri, Offset)) { + BuildMI(*MBB, MII, MI->getDebugLoc(), + TII->get(Hexagon::CONST32_Int_Real), + HEXAGON_RESERVED_REG_1).addImm(Offset); + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::ADD_rr), + HEXAGON_RESERVED_REG_1) + .addReg(FP).addReg(HEXAGON_RESERVED_REG_1); + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_RsPd), + HEXAGON_RESERVED_REG_2).addReg(SrcReg); + BuildMI(*MBB, MII, MI->getDebugLoc(), + TII->get(Hexagon::STriw)) + .addReg(HEXAGON_RESERVED_REG_1) + .addImm(0).addReg(HEXAGON_RESERVED_REG_2); + } else { + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::ADD_ri), + HEXAGON_RESERVED_REG_1).addReg(FP).addImm(Offset); + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_RsPd), + HEXAGON_RESERVED_REG_2).addReg(SrcReg); + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::STriw)) + .addReg(HEXAGON_RESERVED_REG_1) + .addImm(0) + .addReg(HEXAGON_RESERVED_REG_2); + } + } else { + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_RsPd), + HEXAGON_RESERVED_REG_2).addReg(SrcReg); + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::STriw)). + addReg(FP).addImm(Offset).addReg(HEXAGON_RESERVED_REG_2); + } + MII = MBB->erase(MI); + --MII; + } else if (Opc == Hexagon::LDriw_pred) { + // DstReg = LDriw_pred [R30], ofst. + int DstReg = MI->getOperand(0).getReg(); + assert(Hexagon::PredRegsRegClass.contains(DstReg) && + "Not a predicate register"); + unsigned FP = MI->getOperand(1).getReg(); + assert(FP == RegInfo->getFrameRegister() && + "Not a Frame Pointer, Nor a Spill Slot"); + assert(MI->getOperand(2).isImm() && "Not an offset"); + int Offset = MI->getOperand(2).getImm(); + if (!TII->isValidOffset(Hexagon::LDriw, Offset)) { + if (!TII->isValidOffset(Hexagon::ADD_ri, Offset)) { + BuildMI(*MBB, MII, MI->getDebugLoc(), + TII->get(Hexagon::CONST32_Int_Real), + HEXAGON_RESERVED_REG_1).addImm(Offset); + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::ADD_rr), + HEXAGON_RESERVED_REG_1) + .addReg(FP) + .addReg(HEXAGON_RESERVED_REG_1); + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::LDriw), + HEXAGON_RESERVED_REG_2) + .addReg(HEXAGON_RESERVED_REG_1) + .addImm(0); + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_PdRs), + DstReg).addReg(HEXAGON_RESERVED_REG_2); + } else { + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::ADD_ri), + HEXAGON_RESERVED_REG_1).addReg(FP).addImm(Offset); + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::LDriw), + HEXAGON_RESERVED_REG_2) + .addReg(HEXAGON_RESERVED_REG_1) + .addImm(0); + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_PdRs), + DstReg).addReg(HEXAGON_RESERVED_REG_2); + } + } else { + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::LDriw), + HEXAGON_RESERVED_REG_2).addReg(FP).addImm(Offset); + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_PdRs), + DstReg).addReg(HEXAGON_RESERVED_REG_2); + } + MII = MBB->erase(MI); + --MII; + } + } + } + + return true; +} + +} + +//===----------------------------------------------------------------------===// +// Public Constructor Functions +//===----------------------------------------------------------------------===// + +FunctionPass *llvm::createHexagonExpandPredSpillCode(HexagonTargetMachine &TM) { + return new HexagonExpandPredSpillCode(TM); +} diff --git a/lib/Target/Hexagon/HexagonFrameLowering.cpp b/lib/Target/Hexagon/HexagonFrameLowering.cpp new file mode 100644 index 0000000000..5a4e1d2d41 --- /dev/null +++ b/lib/Target/Hexagon/HexagonFrameLowering.cpp @@ -0,0 +1,333 @@ +//==-- HexagonFrameLowering.cpp - Define frame lowering --*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// +//===----------------------------------------------------------------------===// +#include "Hexagon.h" +#include "HexagonInstrInfo.h" +#include "HexagonRegisterInfo.h" +#include "HexagonSubtarget.h" +#include "HexagonTargetMachine.h" +#include "HexagonMachineFunctionInfo.h" +#include "HexagonFrameLowering.h" + +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/MC/MachineLocation.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Type.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include <iostream> + +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Function.h" +using namespace llvm; + +static cl::opt<bool> DisableDeallocRet( + "disable-hexagon-dealloc-ret", + cl::Hidden, + cl::desc("Disable Dealloc Return for Hexagon target")); + +/// determineFrameLayout - Determine the size of the frame and maximum call +/// frame size. +void HexagonFrameLowering::determineFrameLayout(MachineFunction &MF) const { + MachineFrameInfo *MFI = MF.getFrameInfo(); + + // Get the number of bytes to allocate from the FrameInfo. + unsigned FrameSize = MFI->getStackSize(); + + // Get the alignments provided by the target. + unsigned TargetAlign = MF.getTarget().getFrameLowering()->getStackAlignment(); + // Get the maximum call frame size of all the calls. + unsigned maxCallFrameSize = MFI->getMaxCallFrameSize(); + + // If we have dynamic alloca then maxCallFrameSize needs to be aligned so + // that allocations will be aligned. + if (MFI->hasVarSizedObjects()) + maxCallFrameSize = RoundUpToAlignment(maxCallFrameSize, TargetAlign); + + // Update maximum call frame size. + MFI->setMaxCallFrameSize(maxCallFrameSize); + + // Include call frame size in total. + FrameSize += maxCallFrameSize; + + // Make sure the frame is aligned. + FrameSize = RoundUpToAlignment(FrameSize, TargetAlign); + + // Update frame info. + MFI->setStackSize(FrameSize); +} + + +void HexagonFrameLowering::emitPrologue(MachineFunction &MF) const { + MachineBasicBlock &MBB = MF.front(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + MachineModuleInfo &MMI = MF.getMMI(); + MachineBasicBlock::iterator MBBI = MBB.begin(); + const HexagonRegisterInfo *QRI = + static_cast<const HexagonRegisterInfo *>(MF.getTarget().getRegisterInfo()); + DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); + determineFrameLayout(MF); + + // Check if frame moves are needed for EH. + bool needsFrameMoves = MMI.hasDebugInfo() || + !MF.getFunction()->needsUnwindTableEntry(); + + // Get the number of bytes to allocate from the FrameInfo. + int NumBytes = (int) MFI->getStackSize(); + + // LLVM expects allocframe not to be the first instruction in the + // basic block. + MachineBasicBlock::iterator InsertPt = MBB.begin(); + + // + // ALLOCA adjust regs. Iterate over ADJDYNALLOC nodes and change the offset. + // + HexagonMachineFunctionInfo *FuncInfo = + MF.getInfo<HexagonMachineFunctionInfo>(); + const std::vector<MachineInstr*>& AdjustRegs = + FuncInfo->getAllocaAdjustInsts(); + for (std::vector<MachineInstr*>::const_iterator i = AdjustRegs.begin(), + e = AdjustRegs.end(); + i != e; ++i) { + MachineInstr* MI = *i; + assert((MI->getOpcode() == Hexagon::ADJDYNALLOC) && + "Expected adjust alloca node"); + + MachineOperand& MO = MI->getOperand(2); + assert(MO.isImm() && "Expected immediate"); + MO.setImm(MFI->getMaxCallFrameSize()); + } + + std::vector<MachineMove> &Moves = MMI.getFrameMoves(); + + if (needsFrameMoves) { + // Advance CFA. DW_CFA_def_cfa + unsigned FPReg = QRI->getFrameRegister(); + unsigned RAReg = QRI->getRARegister(); + + MachineLocation Dst(MachineLocation::VirtualFP); + MachineLocation Src(FPReg, -8); + Moves.push_back(MachineMove(0, Dst, Src)); + + // R31 = (R31 - #4) + MachineLocation LRDst(RAReg, -4); + MachineLocation LRSrc(RAReg); + Moves.push_back(MachineMove(0, LRDst, LRSrc)); + + // R30 = (R30 - #8) + MachineLocation SPDst(FPReg, -8); + MachineLocation SPSrc(FPReg); + Moves.push_back(MachineMove(0, SPDst, SPSrc)); + } + + // + // Only insert ALLOCFRAME if we need to. + // + if (hasFP(MF)) { + // Check for overflow. + // Hexagon_TODO: Ugh! hardcoding. Is there an API that can be used? + const unsigned int ALLOCFRAME_MAX = 16384; + const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); + + if (NumBytes >= ALLOCFRAME_MAX) { + // Emit allocframe(#0). + BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::ALLOCFRAME)).addImm(0); + + // Subtract offset from frame pointer. + BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::CONST32_Int_Real), + HEXAGON_RESERVED_REG_1).addImm(NumBytes); + BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::SUB_rr), + QRI->getStackRegister()). + addReg(QRI->getStackRegister()). + addReg(HEXAGON_RESERVED_REG_1); + } else { + BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::ALLOCFRAME)).addImm(NumBytes); + } + } +} +// Returns true if MBB has a machine instructions that indicates a tail call +// in the block. +bool HexagonFrameLowering::hasTailCall(MachineBasicBlock &MBB) const { + MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); + unsigned RetOpcode = MBBI->getOpcode(); + + return RetOpcode == Hexagon::TCRETURNtg || RetOpcode == Hexagon::TCRETURNtext;} + +void HexagonFrameLowering::emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const { + MachineBasicBlock::iterator MBBI = prior(MBB.end()); + DebugLoc dl = MBBI->getDebugLoc(); + // + // Only insert deallocframe if we need to. + // + if (hasFP(MF)) { + MachineBasicBlock::iterator MBBI = prior(MBB.end()); + MachineBasicBlock::iterator MBBI_end = MBB.end(); + // + // For Hexagon, we don't need the frame size. + // + MachineFrameInfo *MFI = MF.getFrameInfo(); + int NumBytes = (int) MFI->getStackSize(); + + const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); + + // Replace 'jumpr r31' instruction with dealloc_return for V4 and higher + // versions. + if (STI.hasV4TOps() && MBBI->getOpcode() == Hexagon::JMPR + && !DisableDeallocRet) { + // Remove jumpr node. + MBB.erase(MBBI); + // Add dealloc_return. + BuildMI(MBB, MBBI_end, dl, TII.get(Hexagon::DEALLOC_RET_V4)) + .addImm(NumBytes); + } else { // Add deallocframe for V2 and V3. + BuildMI(MBB, MBBI, dl, TII.get(Hexagon::DEALLOCFRAME)).addImm(NumBytes); + } + } +} + +bool HexagonFrameLowering::hasFP(const MachineFunction &MF) const { + const MachineFrameInfo *MFI = MF.getFrameInfo(); + const HexagonMachineFunctionInfo *FuncInfo = + MF.getInfo<HexagonMachineFunctionInfo>(); + return (MFI->hasCalls() || (MFI->getStackSize() > 0) || + FuncInfo->hasClobberLR() ); +} + +bool +HexagonFrameLowering::spillCalleeSavedRegisters( + MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector<CalleeSavedInfo> &CSI, + const TargetRegisterInfo *TRI) const { + MachineFunction *MF = MBB.getParent(); + const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); + + if (CSI.empty()) { + return false; + } + + // We can only schedule double loads if we spill contiguous callee-saved regs + // For instance, we cannot scheduled double-word loads if we spill r24, + // r26, and r27. + // Hexagon_TODO: We can try to double-word align odd registers for -O2 and + // above. + bool ContiguousRegs = true; + + for (unsigned i = 0; i < CSI.size(); ++i) { + unsigned Reg = CSI[i].getReg(); + + // + // Check if we can use a double-word store. + // + const unsigned* SuperReg = TRI->getSuperRegisters(Reg); + + // Assume that there is exactly one superreg. + assert(SuperReg[0] && !SuperReg[1] && "Expected exactly one superreg"); + bool CanUseDblStore = false; + const TargetRegisterClass* SuperRegClass = 0; + + if (ContiguousRegs && (i < CSI.size()-1)) { + const unsigned* SuperRegNext = TRI->getSuperRegisters(CSI[i+1].getReg()); + assert(SuperRegNext[0] && !SuperRegNext[1] && + "Expected exactly one superreg"); + SuperRegClass = TRI->getMinimalPhysRegClass(SuperReg[0]); + CanUseDblStore = (SuperRegNext[0] == SuperReg[0]); + } + + + if (CanUseDblStore) { + TII.storeRegToStackSlot(MBB, MI, SuperReg[0], true, + CSI[i+1].getFrameIdx(), SuperRegClass, TRI); + MBB.addLiveIn(SuperReg[0]); + ++i; + } else { + // Cannot use a double-word store. + ContiguousRegs = false; + const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); + TII.storeRegToStackSlot(MBB, MI, Reg, true, CSI[i].getFrameIdx(), RC, + TRI); + MBB.addLiveIn(Reg); + } + } + return true; +} + + +bool HexagonFrameLowering::restoreCalleeSavedRegisters( + MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector<CalleeSavedInfo> &CSI, + const TargetRegisterInfo *TRI) const { + + MachineFunction *MF = MBB.getParent(); + const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); + + if (CSI.empty()) { + return false; + } + + // We can only schedule double loads if we spill contiguous callee-saved regs + // For instance, we cannot scheduled double-word loads if we spill r24, + // r26, and r27. + // Hexagon_TODO: We can try to double-word align odd registers for -O2 and + // above. + bool ContiguousRegs = true; + + for (unsigned i = 0; i < CSI.size(); ++i) { + unsigned Reg = CSI[i].getReg(); + + // + // Check if we can use a double-word load. + // + const unsigned* SuperReg = TRI->getSuperRegisters(Reg); + const TargetRegisterClass* SuperRegClass = 0; + + // Assume that there is exactly one superreg. + assert(SuperReg[0] && !SuperReg[1] && "Expected exactly one superreg"); + bool CanUseDblLoad = false; + if (ContiguousRegs && (i < CSI.size()-1)) { + const unsigned* SuperRegNext = TRI->getSuperRegisters(CSI[i+1].getReg()); + assert(SuperRegNext[0] && !SuperRegNext[1] && + "Expected exactly one superreg"); + SuperRegClass = TRI->getMinimalPhysRegClass(SuperReg[0]); + CanUseDblLoad = (SuperRegNext[0] == SuperReg[0]); + } + + + if (CanUseDblLoad) { + TII.loadRegFromStackSlot(MBB, MI, SuperReg[0], CSI[i+1].getFrameIdx(), + SuperRegClass, TRI); + MBB.addLiveIn(SuperReg[0]); + ++i; + } else { + // Cannot use a double-word load. + ContiguousRegs = false; + const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); + TII.loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(), RC, TRI); + MBB.addLiveIn(Reg); + } + } + return true; +} + +int HexagonFrameLowering::getFrameIndexOffset(const MachineFunction &MF, + int FI) const { + return MF.getFrameInfo()->getObjectOffset(FI); +} diff --git a/lib/Target/Hexagon/HexagonFrameLowering.h b/lib/Target/Hexagon/HexagonFrameLowering.h new file mode 100644 index 0000000000..ad87f11e24 --- /dev/null +++ b/lib/Target/Hexagon/HexagonFrameLowering.h @@ -0,0 +1,50 @@ +//=- HexagonFrameLowering.h - Define frame lowering for Hexagon --*- C++ -*--=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef HEXAGON_FRAMEINFO_H +#define HEXAGON_FRAMEINFO_H + +#include "Hexagon.h" +#include "HexagonSubtarget.h" +#include "llvm/Target/TargetFrameLowering.h" + +namespace llvm { + +class HexagonFrameLowering : public TargetFrameLowering { +private: + const HexagonSubtarget &STI; + void determineFrameLayout(MachineFunction &MF) const; + +public: + explicit HexagonFrameLowering(const HexagonSubtarget &sti) + : TargetFrameLowering(StackGrowsDown, 8, 0), STI(sti) { + } + + /// emitProlog/emitEpilog - These methods insert prolog and epilog code into + /// the function. + void emitPrologue(MachineFunction &MF) const; + void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; + virtual bool + spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector<CalleeSavedInfo> &CSI, + const TargetRegisterInfo *TRI) const; + virtual bool + restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector<CalleeSavedInfo> &CSI, + const TargetRegisterInfo *TRI) const; + int getFrameIndexOffset(const MachineFunction &MF, int FI) const; + bool hasFP(const MachineFunction &MF) const; + bool hasTailCall(MachineBasicBlock &MBB) const; +}; + +} // End llvm namespace + +#endif diff --git a/lib/Target/Hexagon/HexagonHardwareLoops.cpp b/lib/Target/Hexagon/HexagonHardwareLoops.cpp new file mode 100644 index 0000000000..c1abc4a8f7 --- /dev/null +++ b/lib/Target/Hexagon/HexagonHardwareLoops.cpp @@ -0,0 +1,644 @@ +//===-- HexagonHardwareLoops.cpp - Identify and generate hardware loops ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass identifies loops where we can generate the Hexagon hardware +// loop instruction. The hardware loop can perform loop branches with a +// zero-cycle overhead. +// +// The pattern that defines the induction variable can changed depending on +// prior optimizations. For example, the IndVarSimplify phase run by 'opt' +// normalizes induction variables, and the Loop Strength Reduction pass +// run by 'llc' may also make changes to the induction variable. +// The pattern detected by this phase is due to running Strength Reduction. +// +// Criteria for hardware loops: +// - Countable loops (w/ ind. var for a trip count) +// - Assumes loops are normalized by IndVarSimplify +// - Try inner-most loops first +// - No nested hardware loops. +// - No function calls in loops. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "hwloops" +#include "llvm/Constants.h" +#include "llvm/PassSupport.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetInstrInfo.h" +#include <algorithm> +#include "Hexagon.h" +#include "HexagonTargetMachine.h" + +using namespace llvm; + +STATISTIC(NumHWLoops, "Number of loops converted to hardware loops"); + +namespace { + class CountValue; + struct HexagonHardwareLoops : public MachineFunctionPass { + MachineLoopInfo *MLI; + MachineRegisterInfo *MRI; + const TargetInstrInfo *TII; + + public: + static char ID; // Pass identification, replacement for typeid + + HexagonHardwareLoops() : MachineFunctionPass(ID) {} + + virtual bool runOnMachineFunction(MachineFunction &MF); + + const char *getPassName() const { return "Hexagon Hardware Loops"; } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addRequired<MachineDominatorTree>(); + AU.addPreserved<MachineDominatorTree>(); + AU.addRequired<MachineLoopInfo>(); + AU.addPreserved<MachineLoopInfo>(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + private: + /// getCanonicalInductionVariable - Check to see if the loop has a canonical + /// induction variable. + /// Should be defined in MachineLoop. Based upon version in class Loop. + const MachineInstr *getCanonicalInductionVariable(MachineLoop *L) const; + + /// getTripCount - Return a loop-invariant LLVM register indicating the + /// number of times the loop will be executed. If the trip-count cannot + /// be determined, this return null. + CountValue *getTripCount(MachineLoop *L) const; + + /// isInductionOperation - Return true if the instruction matches the + /// pattern for an opertion that defines an induction variable. + bool isInductionOperation(const MachineInstr *MI, unsigned IVReg) const; + + /// isInvalidOperation - Return true if the instruction is not valid within + /// a hardware loop. + bool isInvalidLoopOperation(const MachineInstr *MI) const; + + /// containsInavlidInstruction - Return true if the loop contains an + /// instruction that inhibits using the hardware loop. + bool containsInvalidInstruction(MachineLoop *L) const; + + /// converToHardwareLoop - Given a loop, check if we can convert it to a + /// hardware loop. If so, then perform the conversion and return true. + bool convertToHardwareLoop(MachineLoop *L); + + }; + + char HexagonHardwareLoops::ID = 0; + + + // CountValue class - Abstraction for a trip count of a loop. A + // smaller vesrsion of the MachineOperand class without the concerns + // of changing the operand representation. + class CountValue { + public: + enum CountValueType { + CV_Register, + CV_Immediate + }; + private: + CountValueType Kind; + union Values { + unsigned RegNum; + int64_t ImmVal; + Values(unsigned r) : RegNum(r) {} + Values(int64_t i) : ImmVal(i) {} + } Contents; + bool isNegative; + + public: + CountValue(unsigned r, bool neg) : Kind(CV_Register), Contents(r), + isNegative(neg) {} + explicit CountValue(int64_t i) : Kind(CV_Immediate), Contents(i), + isNegative(i < 0) {} + CountValueType getType() const { return Kind; } + bool isReg() const { return Kind == CV_Register; } + bool isImm() const { return Kind == CV_Immediate; } + bool isNeg() const { return isNegative; } + + unsigned getReg() const { + assert(isReg() && "Wrong CountValue accessor"); + return Contents.RegNum; + } + void setReg(unsigned Val) { + Contents.RegNum = Val; + } + int64_t getImm() const { + assert(isImm() && "Wrong CountValue accessor"); + if (isNegative) { + return -Contents.ImmVal; + } + return Contents.ImmVal; + } + void setImm(int64_t Val) { + Contents.ImmVal = Val; + } + + void print(raw_ostream &OS, const TargetMachine *TM = 0) const { + if (isReg()) { OS << PrintReg(getReg()); } + if (isImm()) { OS << getImm(); } + } + }; + + struct HexagonFixupHwLoops : public MachineFunctionPass { + public: + static char ID; // Pass identification, replacement for typeid. + + HexagonFixupHwLoops() : MachineFunctionPass(ID) {} + + virtual bool runOnMachineFunction(MachineFunction &MF); + + const char *getPassName() const { return "Hexagon Hardware Loop Fixup"; } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + private: + /// Maximum distance between the loop instr and the basic block. + /// Just an estimate. + static const unsigned MAX_LOOP_DISTANCE = 200; + + /// fixupLoopInstrs - Check the offset between each loop instruction and + /// the loop basic block to determine if we can use the LOOP instruction + /// or if we need to set the LC/SA registers explicitly. + bool fixupLoopInstrs(MachineFunction &MF); + + /// convertLoopInstr - Add the instruction to set the LC and SA registers + /// explicitly. + void convertLoopInstr(MachineFunction &MF, + MachineBasicBlock::iterator &MII, + RegScavenger &RS); + + }; + + char HexagonFixupHwLoops::ID = 0; + +} // end anonymous namespace + + +/// isHardwareLoop - Returns true if the instruction is a hardware loop +/// instruction. +static bool isHardwareLoop(const MachineInstr *MI) { + return MI->getOpcode() == Hexagon::LOOP0_r || + MI->getOpcode() == Hexagon::LOOP0_i; +} + +/// isCompareEquals - Returns true if the instruction is a compare equals +/// instruction with an immediate operand. +static bool isCompareEqualsImm(const MachineInstr *MI) { + return MI->getOpcode() == Hexagon::CMPEQri; +} + + +/// createHexagonHardwareLoops - Factory for creating +/// the hardware loop phase. +FunctionPass *llvm::createHexagonHardwareLoops() { + return new HexagonHardwareLoops(); +} + + +bool HexagonHardwareLoops::runOnMachineFunction(MachineFunction &MF) { + DEBUG(dbgs() << "********* Hexagon Hardware Loops *********\n"); + + bool Changed = false; + + // get the loop information + MLI = &getAnalysis<MachineLoopInfo>(); + // get the register information + MRI = &MF.getRegInfo(); + // the target specific instructio info. + TII = MF.getTarget().getInstrInfo(); + + for (MachineLoopInfo::iterator I = MLI->begin(), E = MLI->end(); + I != E; ++I) { + MachineLoop *L = *I; + if (!L->getParentLoop()) { + Changed |= convertToHardwareLoop(L); + } + } + + return Changed; +} + +/// getCanonicalInductionVariable - Check to see if the loop has a canonical +/// induction variable. We check for a simple recurrence pattern - an +/// integer recurrence that decrements by one each time through the loop and +/// ends at zero. If so, return the phi node that corresponds to it. +/// +/// Based upon the similar code in LoopInfo except this code is specific to +/// the machine. +/// This method assumes that the IndVarSimplify pass has been run by 'opt'. +/// +const MachineInstr +*HexagonHardwareLoops::getCanonicalInductionVariable(MachineLoop *L) const { + MachineBasicBlock *TopMBB = L->getTopBlock(); + MachineBasicBlock::pred_iterator PI = TopMBB->pred_begin(); + assert(PI != TopMBB->pred_end() && + "Loop must have more than one incoming edge!"); + MachineBasicBlock *Backedge = *PI++; + if (PI == TopMBB->pred_end()) return 0; // dead loop + MachineBasicBlock *Incoming = *PI++; + if (PI != TopMBB->pred_end()) return 0; // multiple backedges? + + // make sure there is one incoming and one backedge and determine which + // is which. + if (L->contains(Incoming)) { + if (L->contains(Backedge)) + return 0; + std::swap(Incoming, Backedge); + } else if (!L->contains(Backedge)) + return 0; + + // Loop over all of the PHI nodes, looking for a canonical induction variable: + // - The PHI node is "reg1 = PHI reg2, BB1, reg3, BB2". + // - The recurrence comes from the backedge. + // - the definition is an induction operatio.n + for (MachineBasicBlock::iterator I = TopMBB->begin(), E = TopMBB->end(); + I != E && I->isPHI(); ++I) { + const MachineInstr *MPhi = &*I; + unsigned DefReg = MPhi->getOperand(0).getReg(); + for (unsigned i = 1; i != MPhi->getNumOperands(); i += 2) { + // Check each operand for the value from the backedge. + MachineBasicBlock *MBB = MPhi->getOperand(i+1).getMBB(); + if (L->contains(MBB)) { // operands comes from the backedge + // Check if the definition is an induction operation. + const MachineInstr *DI = MRI->getVRegDef(MPhi->getOperand(i).getReg()); + if (isInductionOperation(DI, DefReg)) { + return MPhi; + } + } + } + } + return 0; +} + +/// getTripCount - Return a loop-invariant LLVM value indicating the +/// number of times the loop will be executed. The trip count can +/// be either a register or a constant value. If the trip-count +/// cannot be determined, this returns null. +/// +/// We find the trip count from the phi instruction that defines the +/// induction variable. We follow the links to the CMP instruction +/// to get the trip count. +/// +/// Based upon getTripCount in LoopInfo. +/// +CountValue *HexagonHardwareLoops::getTripCount(MachineLoop *L) const { + // Check that the loop has a induction variable. + const MachineInstr *IV_Inst = getCanonicalInductionVariable(L); + if (IV_Inst == 0) return 0; + + // Canonical loops will end with a 'cmpeq_ri IV, Imm', + // if Imm is 0, get the count from the PHI opnd + // if Imm is -M, than M is the count + // Otherwise, Imm is the count + const MachineOperand *IV_Opnd; + const MachineOperand *InitialValue; + if (!L->contains(IV_Inst->getOperand(2).getMBB())) { + InitialValue = &IV_Inst->getOperand(1); + IV_Opnd = &IV_Inst->getOperand(3); + } else { + InitialValue = &IV_Inst->getOperand(3); + IV_Opnd = &IV_Inst->getOperand(1); + } + + // Look for the cmp instruction to determine if we + // can get a useful trip count. The trip count can + // be either a register or an immediate. The location + // of the value depends upon the type (reg or imm). + while ((IV_Opnd = IV_Opnd->getNextOperandForReg())) { + const MachineInstr *MI = IV_Opnd->getParent(); + if (L->contains(MI) && isCompareEqualsImm(MI)) { + const MachineOperand &MO = MI->getOperand(2); + assert(MO.isImm() && "IV Cmp Operand should be 0"); + int64_t ImmVal = MO.getImm(); + + const MachineInstr *IV_DefInstr = MRI->getVRegDef(IV_Opnd->getReg()); + assert(L->contains(IV_DefInstr->getParent()) && + "IV definition should occurs in loop"); + int64_t iv_value = IV_DefInstr->getOperand(2).getImm(); + + if (ImmVal == 0) { + // Make sure the induction variable changes by one on each iteration. + if (iv_value != 1 && iv_value != -1) { + return 0; + } + return new CountValue(InitialValue->getReg(), iv_value > 0); + } else { + assert(InitialValue->isReg() && "Expecting register for init value"); + const MachineInstr *DefInstr = MRI->getVRegDef(InitialValue->getReg()); + if (DefInstr && DefInstr->getOpcode() == Hexagon::TFRI) { + int64_t count = ImmVal - DefInstr->getOperand(1).getImm(); + if ((count % iv_value) != 0) { + return 0; + } + return new CountValue(count/iv_value); + } + } + } + } + return 0; +} + +/// isInductionOperation - return true if the operation is matches the +/// pattern that defines an induction variable: +/// add iv, c +/// +bool +HexagonHardwareLoops::isInductionOperation(const MachineInstr *MI, + unsigned IVReg) const { + return (MI->getOpcode() == + Hexagon::ADD_ri && MI->getOperand(1).getReg() == IVReg); +} + +/// isInvalidOperation - Return true if the operation is invalid within +/// hardware loop. +bool +HexagonHardwareLoops::isInvalidLoopOperation(const MachineInstr *MI) const { + + // call is not allowed because the callee may use a hardware loop + if (MI->getDesc().isCall()) { + return true; + } + // do not allow nested hardware loops + if (isHardwareLoop(MI)) { + return true; + } + // check if the instruction defines a hardware loop register + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isDef() && + (MO.getReg() == Hexagon::LC0 || MO.getReg() == Hexagon::LC1 || + MO.getReg() == Hexagon::SA0 || MO.getReg() == Hexagon::SA0)) { + return true; + } + } + return false; +} + +/// containsInvalidInstruction - Return true if the loop contains +/// an instruction that inhibits the use of the hardware loop function. +/// +bool HexagonHardwareLoops::containsInvalidInstruction(MachineLoop *L) const { + const std::vector<MachineBasicBlock*> Blocks = L->getBlocks(); + for (unsigned i = 0, e = Blocks.size(); i != e; ++i) { + MachineBasicBlock *MBB = Blocks[i]; + for (MachineBasicBlock::iterator + MII = MBB->begin(), E = MBB->end(); MII != E; ++MII) { + const MachineInstr *MI = &*MII; + if (isInvalidLoopOperation(MI)) { + return true; + } + } + } + return false; +} + +/// converToHardwareLoop - check if the loop is a candidate for +/// converting to a hardware loop. If so, then perform the +/// transformation. +/// +/// This function works on innermost loops first. A loop can +/// be converted if it is a counting loop; either a register +/// value or an immediate. +/// +/// The code makes several assumptions about the representation +/// of the loop in llvm. +bool HexagonHardwareLoops::convertToHardwareLoop(MachineLoop *L) { + bool Changed = false; + // Process nested loops first. + for (MachineLoop::iterator I = L->begin(), E = L->end(); I != E; ++I) { + Changed |= convertToHardwareLoop(*I); + } + // If a nested loop has been converted, then we can't convert this loop. + if (Changed) { + return Changed; + } + // Are we able to determine the trip count for the loop? + CountValue *TripCount = getTripCount(L); + if (TripCount == 0) { + return false; + } + // Does the loop contain any invalid instructions? + if (containsInvalidInstruction(L)) { + return false; + } + MachineBasicBlock *Preheader = L->getLoopPreheader(); + // No preheader means there's not place for the loop instr. + if (Preheader == 0) { + return false; + } + MachineBasicBlock::iterator InsertPos = Preheader->getFirstTerminator(); + + MachineBasicBlock *LastMBB = L->getExitingBlock(); + // Don't generate hw loop if the loop has more than one exit. + if (LastMBB == 0) { + return false; + } + MachineBasicBlock::iterator LastI = LastMBB->getFirstTerminator(); + + // Determine the loop start. + MachineBasicBlock *LoopStart = L->getTopBlock(); + if (L->getLoopLatch() != LastMBB) { + // When the exit and latch are not the same, use the latch block as the + // start. + // The loop start address is used only after the 1st iteration, and the loop + // latch may contains instrs. that need to be executed after the 1st iter. + LoopStart = L->getLoopLatch(); + // Make sure the latch is a successor of the exit, otherwise it won't work. + if (!LastMBB->isSuccessor(LoopStart)) { + return false; + } + } + + // Convert the loop to a hardware loop + DEBUG(dbgs() << "Change to hardware loop at "; L->dump()); + + if (TripCount->isReg()) { + // Create a copy of the loop count register. + MachineFunction *MF = LastMBB->getParent(); + const TargetRegisterClass *RC = + MF->getRegInfo().getRegClass(TripCount->getReg()); + unsigned CountReg = MF->getRegInfo().createVirtualRegister(RC); + BuildMI(*Preheader, InsertPos, InsertPos->getDebugLoc(), + TII->get(TargetOpcode::COPY), CountReg).addReg(TripCount->getReg()); + if (TripCount->isNeg()) { + unsigned CountReg1 = CountReg; + CountReg = MF->getRegInfo().createVirtualRegister(RC); + BuildMI(*Preheader, InsertPos, InsertPos->getDebugLoc(), + TII->get(Hexagon::NEG), CountReg).addReg(CountReg1); + } + + // Add the Loop instruction to the begining of the loop. + BuildMI(*Preheader, InsertPos, InsertPos->getDebugLoc(), + TII->get(Hexagon::LOOP0_r)).addMBB(LoopStart).addReg(CountReg); + } else { + assert(TripCount->isImm() && "Expecting immedate vaule for trip count"); + // Add the Loop immediate instruction to the beginning of the loop. + int64_t CountImm = TripCount->getImm(); + BuildMI(*Preheader, InsertPos, InsertPos->getDebugLoc(), + TII->get(Hexagon::LOOP0_i)).addMBB(LoopStart).addImm(CountImm); + } + + // Make sure the loop start always has a reference in the CFG. We need to + // create a BlockAddress operand to get this mechanism to work both the + // MachineBasicBlock and BasicBlock objects need the flag set. + LoopStart->setHasAddressTaken(); + // This line is needed to set the hasAddressTaken flag on the BasicBlock + // object + BlockAddress::get(const_cast<BasicBlock *>(LoopStart->getBasicBlock())); + + // Replace the loop branch with an endloop instruction. + DebugLoc dl = LastI->getDebugLoc(); + BuildMI(*LastMBB, LastI, dl, TII->get(Hexagon::ENDLOOP0)).addMBB(LoopStart); + + // The loop ends with either: + // - a conditional branch followed by an unconditional branch, or + // - a conditional branch to the loop start. + if (LastI->getOpcode() == Hexagon::JMP_Pred || + LastI->getOpcode() == Hexagon::JMP_PredNot) { + // delete one and change/add an uncond. branch to out of the loop + MachineBasicBlock *BranchTarget = LastI->getOperand(1).getMBB(); + LastI = LastMBB->erase(LastI); + if (!L->contains(BranchTarget)) { + if (LastI != LastMBB->end()) { + TII->RemoveBranch(*LastMBB); + } + SmallVector<MachineOperand, 0> Cond; + TII->InsertBranch(*LastMBB, BranchTarget, 0, Cond, dl); + } + } else { + // Conditional branch to loop start; just delete it. + LastMBB->erase(LastI); + } + delete TripCount; + + ++NumHWLoops; + return true; +} + +/// createHexagonFixupHwLoops - Factory for creating the hardware loop +/// phase. +FunctionPass *llvm::createHexagonFixupHwLoops() { + return new HexagonFixupHwLoops(); +} + +bool HexagonFixupHwLoops::runOnMachineFunction(MachineFunction &MF) { + DEBUG(dbgs() << "****** Hexagon Hardware Loop Fixup ******\n"); + + bool Changed = fixupLoopInstrs(MF); + return Changed; +} + +/// fixupLoopInsts - For Hexagon, if the loop label is to far from the +/// loop instruction then we need to set the LC0 and SA0 registers +/// explicitly instead of using LOOP(start,count). This function +/// checks the distance, and generates register assignments if needed. +/// +/// This function makes two passes over the basic blocks. The first +/// pass computes the offset of the basic block from the start. +/// The second pass checks all the loop instructions. +bool HexagonFixupHwLoops::fixupLoopInstrs(MachineFunction &MF) { + + // Offset of the current instruction from the start. + unsigned InstOffset = 0; + // Map for each basic block to it's first instruction. + DenseMap<MachineBasicBlock*, unsigned> BlockToInstOffset; + + // First pass - compute the offset of each basic block. + for (MachineFunction::iterator MBB = MF.begin(), MBBe = MF.end(); + MBB != MBBe; ++MBB) { + BlockToInstOffset[MBB] = InstOffset; + InstOffset += (MBB->size() * 4); + } + + // Second pass - check each loop instruction to see if it needs to + // be converted. + InstOffset = 0; + bool Changed = false; + RegScavenger RS; + + // Loop over all the basic blocks. + for (MachineFunction::iterator MBB = MF.begin(), MBBe = MF.end(); + MBB != MBBe; ++MBB) { + InstOffset = BlockToInstOffset[MBB]; + RS.enterBasicBlock(MBB); + + // Loop over all the instructions. + MachineBasicBlock::iterator MIE = MBB->end(); + MachineBasicBlock::iterator MII = MBB->begin(); + while (MII != MIE) { + if (isHardwareLoop(MII)) { + RS.forward(MII); + assert(MII->getOperand(0).isMBB() && + "Expect a basic block as loop operand"); + int diff = InstOffset - BlockToInstOffset[MII->getOperand(0).getMBB()]; + diff = (diff > 0 ? diff : -diff); + if ((unsigned)diff > MAX_LOOP_DISTANCE) { + // Convert to explicity setting LC0 and SA0. + convertLoopInstr(MF, MII, RS); + MII = MBB->erase(MII); + Changed = true; + } else { + ++MII; + } + } else { + ++MII; + } + InstOffset += 4; + } + } + + return Changed; + +} + +/// convertLoopInstr - convert a loop instruction to a sequence of instructions +/// that set the lc and sa register explicitly. +void HexagonFixupHwLoops::convertLoopInstr(MachineFunction &MF, + MachineBasicBlock::iterator &MII, + RegScavenger &RS) { + const TargetInstrInfo *TII = MF.getTarget().getInstrInfo(); + MachineBasicBlock *MBB = MII->getParent(); + DebugLoc DL = MII->getDebugLoc(); + unsigned Scratch = RS.scavengeRegister(Hexagon::IntRegsRegisterClass, MII, 0); + + // First, set the LC0 with the trip count. + if (MII->getOperand(1).isReg()) { + // Trip count is a register + BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::LC0) + .addReg(MII->getOperand(1).getReg()); + } else { + // Trip count is an immediate. + BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFRI), Scratch) + .addImm(MII->getOperand(1).getImm()); + BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::LC0) + .addReg(Scratch); + } + // Then, set the SA0 with the loop start address. + BuildMI(*MBB, MII, DL, TII->get(Hexagon::CONST32_Label), Scratch) + .addMBB(MII->getOperand(0).getMBB()); + BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::SA0).addReg(Scratch); +} diff --git a/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp b/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp new file mode 100644 index 0000000000..4deab9f6b7 --- /dev/null +++ b/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp @@ -0,0 +1,1495 @@ +//==-- HexagonISelDAGToDAG.cpp - A dag to dag inst selector for Hexagon ----==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines an instruction selector for the Hexagon target. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "hexagon-isel" +#include "HexagonISelLowering.h" +#include "HexagonTargetMachine.h" +#include "llvm/Intrinsics.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" + +using namespace llvm; + + +//===----------------------------------------------------------------------===// +// Instruction Selector Implementation +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------===// +/// HexagonDAGToDAGISel - Hexagon specific code to select Hexagon machine +/// instructions for SelectionDAG operations. +/// +namespace { +class HexagonDAGToDAGISel : public SelectionDAGISel { + /// Subtarget - Keep a pointer to the Hexagon Subtarget around so that we can + /// make the right decision when generating code for different targets. + const HexagonSubtarget &Subtarget; + + // Keep a reference to HexagonTargetMachine. + HexagonTargetMachine& TM; + const HexagonInstrInfo *TII; + +public: + explicit HexagonDAGToDAGISel(HexagonTargetMachine &targetmachine) + : SelectionDAGISel(targetmachine), + Subtarget(targetmachine.getSubtarget<HexagonSubtarget>()), + TM(targetmachine), + TII(static_cast<const HexagonInstrInfo*>(TM.getInstrInfo())) { + + } + + SDNode *Select(SDNode *N); + + // Complex Pattern Selectors. + bool SelectADDRri(SDValue& N, SDValue &R1, SDValue &R2); + bool SelectADDRriS11_0(SDValue& N, SDValue &R1, SDValue &R2); + bool SelectADDRriS11_1(SDValue& N, SDValue &R1, SDValue &R2); + bool SelectADDRriS11_2(SDValue& N, SDValue &R1, SDValue &R2); + bool SelectMEMriS11_2(SDValue& Addr, SDValue &Base, SDValue &Offset); + bool SelectADDRriS11_3(SDValue& N, SDValue &R1, SDValue &R2); + bool SelectADDRrr(SDValue &Addr, SDValue &Base, SDValue &Offset); + bool SelectADDRriU6_0(SDValue& N, SDValue &R1, SDValue &R2); + bool SelectADDRriU6_1(SDValue& N, SDValue &R1, SDValue &R2); + bool SelectADDRriU6_2(SDValue& N, SDValue &R1, SDValue &R2); + + virtual const char *getPassName() const { + return "Hexagon DAG->DAG Pattern Instruction Selection"; + } + + /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for + /// inline asm expressions. + virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, + char ConstraintCode, + std::vector<SDValue> &OutOps); + bool SelectAddr(SDNode *Op, SDValue Addr, SDValue &Base, SDValue &Offset); + + SDNode *SelectLoad(SDNode *N); + SDNode *SelectBaseOffsetLoad(LoadSDNode *LD, DebugLoc dl); + SDNode *SelectIndexedLoad(LoadSDNode *LD, DebugLoc dl); + SDNode *SelectIndexedLoadZeroExtend64(LoadSDNode *LD, unsigned Opcode, + DebugLoc dl); + SDNode *SelectIndexedLoadSignExtend64(LoadSDNode *LD, unsigned Opcode, + DebugLoc dl); + SDNode *SelectBaseOffsetStore(StoreSDNode *ST, DebugLoc dl); + SDNode *SelectIndexedStore(StoreSDNode *ST, DebugLoc dl); + SDNode *SelectStore(SDNode *N); + SDNode *SelectSHL(SDNode *N); + SDNode *SelectSelect(SDNode *N); + SDNode *SelectTruncate(SDNode *N); + SDNode *SelectMul(SDNode *N); + SDNode *SelectZeroExtend(SDNode *N); + SDNode *SelectIntrinsicWOChain(SDNode *N); + SDNode *SelectConstant(SDNode *N); + SDNode *SelectAdd(SDNode *N); + + // Include the pieces autogenerated from the target description. +#include "HexagonGenDAGISel.inc" +}; +} // end anonymous namespace + + +/// createHexagonISelDag - This pass converts a legalized DAG into a +/// Hexagon-specific DAG, ready for instruction scheduling. +/// +FunctionPass *llvm::createHexagonISelDag(HexagonTargetMachine &TM) { + return new HexagonDAGToDAGISel(TM); +} + +static bool IsS11_0_Offset(SDNode * S) { + ConstantSDNode *N = cast<ConstantSDNode>(S); + + // immS16 predicate - True if the immediate fits in a 16-bit sign extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isInt<11>(v); +} + + +static bool IsS11_1_Offset(SDNode * S) { + ConstantSDNode *N = cast<ConstantSDNode>(S); + + // immS16 predicate - True if the immediate fits in a 16-bit sign extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedInt<11,1>(v); +} + + +static bool IsS11_2_Offset(SDNode * S) { + ConstantSDNode *N = cast<ConstantSDNode>(S); + + // immS16 predicate - True if the immediate fits in a 16-bit sign extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedInt<11,2>(v); +} + + +static bool IsS11_3_Offset(SDNode * S) { + ConstantSDNode *N = cast<ConstantSDNode>(S); + + // immS16 predicate - True if the immediate fits in a 16-bit sign extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedInt<11,3>(v); +} + + +static bool IsU6_0_Offset(SDNode * S) { + ConstantSDNode *N = cast<ConstantSDNode>(S); + + // u6 predicate - True if the immediate fits in a 6-bit unsigned extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isUInt<6>(v); +} + + +static bool IsU6_1_Offset(SDNode * S) { + ConstantSDNode *N = cast<ConstantSDNode>(S); + + // u6 predicate - True if the immediate fits in a 6-bit unsigned extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedUInt<6,1>(v); +} + + +static bool IsU6_2_Offset(SDNode * S) { + ConstantSDNode *N = cast<ConstantSDNode>(S); + + // u6 predicate - True if the immediate fits in a 6-bit unsigned extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedUInt<6,2>(v); +} + + +// Intrinsics that return a a predicate. +static unsigned doesIntrinsicReturnPredicate(unsigned ID) +{ + switch (ID) { + default: + return 0; + case Intrinsic::hexagon_C2_cmpeq: + case Intrinsic::hexagon_C2_cmpgt: + case Intrinsic::hexagon_C2_cmpgtu: + case Intrinsic::hexagon_C2_cmpgtup: + case Intrinsic::hexagon_C2_cmpgtp: + case Intrinsic::hexagon_C2_cmpeqp: + case Intrinsic::hexagon_C2_bitsset: + case Intrinsic::hexagon_C2_bitsclr: + case Intrinsic::hexagon_C2_cmpeqi: + case Intrinsic::hexagon_C2_cmpgti: + case Intrinsic::hexagon_C2_cmpgtui: + case Intrinsic::hexagon_C2_cmpgei: + case Intrinsic::hexagon_C2_cmpgeui: + case Intrinsic::hexagon_C2_cmplt: + case Intrinsic::hexagon_C2_cmpltu: + case Intrinsic::hexagon_C2_bitsclri: + case Intrinsic::hexagon_C2_and: + case Intrinsic::hexagon_C2_or: + case Intrinsic::hexagon_C2_xor: + case Intrinsic::hexagon_C2_andn: + case Intrinsic::hexagon_C2_not: + case Intrinsic::hexagon_C2_orn: + case Intrinsic::hexagon_C2_pxfer_map: + case Intrinsic::hexagon_C2_any8: + case Intrinsic::hexagon_C2_all8: + case Intrinsic::hexagon_A2_vcmpbeq: + case Intrinsic::hexagon_A2_vcmpbgtu: + case Intrinsic::hexagon_A2_vcmpheq: + case Intrinsic::hexagon_A2_vcmphgt: + case Intrinsic::hexagon_A2_vcmphgtu: + case Intrinsic::hexagon_A2_vcmpweq: + case Intrinsic::hexagon_A2_vcmpwgt: + case Intrinsic::hexagon_A2_vcmpwgtu: + case Intrinsic::hexagon_C2_tfrrp: + case Intrinsic::hexagon_S2_tstbit_i: + case Intrinsic::hexagon_S2_tstbit_r: + return 1; + } +} + + +// Intrinsics that have predicate operands. +static unsigned doesIntrinsicContainPredicate(unsigned ID) +{ + switch (ID) { + default: + return 0; + case Intrinsic::hexagon_C2_tfrpr: + return Hexagon::TFR_RsPd; + case Intrinsic::hexagon_C2_and: + return Hexagon::AND_pp; + case Intrinsic::hexagon_C2_xor: + return Hexagon::XOR_pp; + case Intrinsic::hexagon_C2_or: + return Hexagon::OR_pp; + case Intrinsic::hexagon_C2_not: + return Hexagon::NOT_pp; + case Intrinsic::hexagon_C2_any8: + return Hexagon::ANY_pp; + case Intrinsic::hexagon_C2_all8: + return Hexagon::ALL_pp; + case Intrinsic::hexagon_C2_vitpack: + return Hexagon::VITPACK_pp; + case Intrinsic::hexagon_C2_mask: + return Hexagon::MASK_p; + case Intrinsic::hexagon_C2_mux: + return Hexagon::MUX_rr; + + // Mapping hexagon_C2_muxir to MUX_pri. This is pretty weird - but + // that's how it's mapped in q6protos.h. + case Intrinsic::hexagon_C2_muxir: + return Hexagon::MUX_ri; + + // Mapping hexagon_C2_muxri to MUX_pir. This is pretty weird - but + // that's how it's mapped in q6protos.h. + case Intrinsic::hexagon_C2_muxri: + return Hexagon::MUX_ir; + + case Intrinsic::hexagon_C2_muxii: + return Hexagon::MUX_ii; + case Intrinsic::hexagon_C2_vmux: + return Hexagon::VMUX_prr64; + case Intrinsic::hexagon_S2_valignrb: + return Hexagon::VALIGN_rrp; + case Intrinsic::hexagon_S2_vsplicerb: + return Hexagon::VSPLICE_rrp; + } +} + + +static bool OffsetFitsS11(EVT MemType, int64_t Offset) { + if (MemType == MVT::i64 && isShiftedInt<11,3>(Offset)) { + return true; + } + if (MemType == MVT::i32 && isShiftedInt<11,2>(Offset)) { + return true; + } + if (MemType == MVT::i16 && isShiftedInt<11,1>(Offset)) { + return true; + } + if (MemType == MVT::i8 && isInt<11>(Offset)) { + return true; + } + return false; +} + + +// +// Try to lower loads of GlobalAdresses into base+offset loads. Custom +// lowering for GlobalAddress nodes has already turned it into a +// CONST32. +// +SDNode *HexagonDAGToDAGISel::SelectBaseOffsetLoad(LoadSDNode *LD, DebugLoc dl) { + EVT LoadedVT = LD->getMemoryVT(); + SDValue Chain = LD->getChain(); + SDNode* Const32 = LD->getBasePtr().getNode(); + unsigned Opcode = 0; + + if (Const32->getOpcode() == HexagonISD::CONST32 && + ISD::isNormalLoad(LD)) { + SDValue Base = Const32->getOperand(0); + EVT LoadedVT = LD->getMemoryVT(); + int64_t Offset = cast<GlobalAddressSDNode>(Base)->getOffset(); + if (Offset != 0 && OffsetFitsS11(LoadedVT, Offset)) { + MVT PointerTy = TLI.getPointerTy(); + const GlobalValue* GV = + cast<GlobalAddressSDNode>(Base)->getGlobal(); + SDValue TargAddr = + CurDAG->getTargetGlobalAddress(GV, dl, PointerTy, 0); + SDNode* NewBase = CurDAG->getMachineNode(Hexagon::CONST32_set, + dl, PointerTy, + TargAddr); + // Figure out base + offset opcode + if (LoadedVT == MVT::i64) Opcode = Hexagon::LDrid_indexed; + else if (LoadedVT == MVT::i32) Opcode = Hexagon::LDriw_indexed; + else if (LoadedVT == MVT::i16) Opcode = Hexagon::LDrih_indexed; + else if (LoadedVT == MVT::i8) Opcode = Hexagon::LDrib_indexed; + else assert (0 && "unknown memory type"); + + // Build indexed load. + SDValue TargetConstOff = CurDAG->getTargetConstant(Offset, PointerTy); + SDNode* Result = CurDAG->getMachineNode(Opcode, dl, + LD->getValueType(0), + MVT::Other, + SDValue(NewBase,0), + TargetConstOff, + Chain); + MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); + MemOp[0] = LD->getMemOperand(); + cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1); + ReplaceUses(LD, Result); + return Result; + } + } + + return SelectCode(LD); +} + + +SDNode *HexagonDAGToDAGISel::SelectIndexedLoadSignExtend64(LoadSDNode *LD, + unsigned Opcode, + DebugLoc dl) +{ + SDValue Chain = LD->getChain(); + EVT LoadedVT = LD->getMemoryVT(); + SDValue Base = LD->getBasePtr(); + SDValue Offset = LD->getOffset(); + SDNode *OffsetNode = Offset.getNode(); + int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue(); + SDValue N1 = LD->getOperand(1); + SDValue CPTmpN1_0; + SDValue CPTmpN1_1; + if (SelectADDRriS11_2(N1, CPTmpN1_0, CPTmpN1_1) && + N1.getNode()->getValueType(0) == MVT::i32) { + if (TII->isValidAutoIncImm(LoadedVT, Val)) { + SDValue TargetConst = CurDAG->getTargetConstant(Val, MVT::i32); + SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::i32, + MVT::Other, Base, TargetConst, + Chain); + SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::SXTW, dl, MVT::i64, + SDValue(Result_1, 0)); + MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); + MemOp[0] = LD->getMemOperand(); + cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1); + const SDValue Froms[] = { SDValue(LD, 0), + SDValue(LD, 1), + SDValue(LD, 2) + }; + const SDValue Tos[] = { SDValue(Result_2, 0), + SDValue(Result_1, 1), + SDValue(Result_1, 2) + }; + ReplaceUses(Froms, Tos, 3); + return Result_2; + } + SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); + SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32); + SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, + MVT::Other, Base, TargetConst0, + Chain); + SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::SXTW, dl, + MVT::i64, SDValue(Result_1, 0)); + SDNode* Result_3 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, + MVT::i32, Base, TargetConstVal, + SDValue(Result_1, 1)); + MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); + MemOp[0] = LD->getMemOperand(); + cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1); + const SDValue Froms[] = { SDValue(LD, 0), + SDValue(LD, 1), + SDValue(LD, 2) + }; + const SDValue Tos[] = { SDValue(Result_2, 0), + SDValue(Result_3, 0), + SDValue(Result_1, 1) + }; + ReplaceUses(Froms, Tos, 3); + return Result_2; + } + return SelectCode(LD); +} + + +SDNode *HexagonDAGToDAGISel::SelectIndexedLoadZeroExtend64(LoadSDNode *LD, + unsigned Opcode, + DebugLoc dl) +{ + SDValue Chain = LD->getChain(); + EVT LoadedVT = LD->getMemoryVT(); + SDValue Base = LD->getBasePtr(); + SDValue Offset = LD->getOffset(); + SDNode *OffsetNode = Offset.getNode(); + int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue(); + SDValue N1 = LD->getOperand(1); + SDValue CPTmpN1_0; + SDValue CPTmpN1_1; + if (SelectADDRriS11_2(N1, CPTmpN1_0, CPTmpN1_1) && + N1.getNode()->getValueType(0) == MVT::i32) { + if (TII->isValidAutoIncImm(LoadedVT, Val)) { + SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32); + SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); + SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, + MVT::i32, MVT::Other, Base, + TargetConstVal, Chain); + SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32, + TargetConst0); + SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl, + MVT::i64, MVT::Other, + SDValue(Result_2,0), + SDValue(Result_1,0)); + MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); + MemOp[0] = LD->getMemOperand(); + cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1); + const SDValue Froms[] = { SDValue(LD, 0), + SDValue(LD, 1), + SDValue(LD, 2) + }; + const SDValue Tos[] = { SDValue(Result_3, 0), + SDValue(Result_1, 1), + SDValue(Result_1, 2) + }; + ReplaceUses(Froms, Tos, 3); + return Result_3; + } + + // Generate an indirect load. + SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); + SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32); + SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, + MVT::Other, + Base, TargetConst0, Chain); + SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32, + TargetConst0); + SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl, + MVT::i64, MVT::Other, + SDValue(Result_2,0), + SDValue(Result_1,0)); + // Add offset to base. + SDNode* Result_4 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32, + Base, TargetConstVal, + SDValue(Result_1, 1)); + MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); + MemOp[0] = LD->getMemOperand(); + cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1); + const SDValue Froms[] = { SDValue(LD, 0), + SDValue(LD, 1), + SDValue(LD, 2) + }; + const SDValue Tos[] = { SDValue(Result_3, 0), // Load value. + SDValue(Result_4, 0), // New address. + SDValue(Result_1, 1) + }; + ReplaceUses(Froms, Tos, 3); + return Result_3; + } + + return SelectCode(LD); +} + + +SDNode *HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, DebugLoc dl) { + SDValue Chain = LD->getChain(); + SDValue Base = LD->getBasePtr(); + SDValue Offset = LD->getOffset(); + SDNode *OffsetNode = Offset.getNode(); + // Get the constant value. + int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue(); + EVT LoadedVT = LD->getMemoryVT(); + unsigned Opcode = 0; + + // Check for zero ext loads. + bool zextval = (LD->getExtensionType() == ISD::ZEXTLOAD); + + // Figure out the opcode. + if (LoadedVT == MVT::i64) { + if (TII->isValidAutoIncImm(LoadedVT, Val)) + Opcode = Hexagon::POST_LDrid; + else + Opcode = Hexagon::LDrid; + } else if (LoadedVT == MVT::i32) { + if (TII->isValidAutoIncImm(LoadedVT, Val)) + Opcode = Hexagon::POST_LDriw; + else + Opcode = Hexagon::LDriw; + } else if (LoadedVT == MVT::i16) { + if (TII->isValidAutoIncImm(LoadedVT, Val)) + Opcode = zextval ? Hexagon::POST_LDriuh : Hexagon::POST_LDrih; + else + Opcode = zextval ? Hexagon::LDriuh : Hexagon::LDrih; + } else if (LoadedVT == MVT::i8) { + if (TII->isValidAutoIncImm(LoadedVT, Val)) + Opcode = zextval ? Hexagon::POST_LDriub : Hexagon::POST_LDrib; + else + Opcode = zextval ? Hexagon::LDriub : Hexagon::LDrib; + } else + assert (0 && "unknown memory type"); + + // For zero ext i64 loads, we need to add combine instructions. + if (LD->getValueType(0) == MVT::i64 && + LD->getExtensionType() == ISD::ZEXTLOAD) { + return SelectIndexedLoadZeroExtend64(LD, Opcode, dl); + } + if (LD->getValueType(0) == MVT::i64 && + LD->getExtensionType() == ISD::SEXTLOAD) { + // Handle sign ext i64 loads. + return SelectIndexedLoadSignExtend64(LD, Opcode, dl); + } + if (TII->isValidAutoIncImm(LoadedVT, Val)) { + SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32); + SDNode* Result = CurDAG->getMachineNode(Opcode, dl, + LD->getValueType(0), + MVT::i32, MVT::Other, Base, + TargetConstVal, Chain); + MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); + MemOp[0] = LD->getMemOperand(); + cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1); + const SDValue Froms[] = { SDValue(LD, 0), + SDValue(LD, 1), + SDValue(LD, 2) + }; + const SDValue Tos[] = { SDValue(Result, 0), + SDValue(Result, 1), + SDValue(Result, 2) + }; + ReplaceUses(Froms, Tos, 3); + return Result; + } else { + SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); + SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32); + SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl, + LD->getValueType(0), + MVT::Other, Base, TargetConst0, + Chain); + SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32, + Base, TargetConstVal, + SDValue(Result_1, 1)); + MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); + MemOp[0] = LD->getMemOperand(); + cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1); + const SDValue Froms[] = { SDValue(LD, 0), + SDValue(LD, 1), + SDValue(LD, 2) + }; + const SDValue Tos[] = { SDValue(Result_1, 0), + SDValue(Result_2, 0), + SDValue(Result_1, 1) + }; + ReplaceUses(Froms, Tos, 3); + return Result_1; + } + + return SelectCode(LD); +} + + +SDNode *HexagonDAGToDAGISel::SelectLoad(SDNode *N) { + SDNode *result; + DebugLoc dl = N->getDebugLoc(); + LoadSDNode *LD = cast<LoadSDNode>(N); + ISD::MemIndexedMode AM = LD->getAddressingMode(); + + // Handle indexed loads. + if (AM != ISD::UNINDEXED) { + result = SelectIndexedLoad(LD, dl); + } else { + result = SelectBaseOffsetLoad(LD, dl); + } + + return result; +} + + +SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, DebugLoc dl) { + SDValue Chain = ST->getChain(); + SDValue Base = ST->getBasePtr(); + SDValue Offset = ST->getOffset(); + SDValue Value = ST->getValue(); + SDNode *OffsetNode = Offset.getNode(); + // Get the constant value. + int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue(); + EVT StoredVT = ST->getMemoryVT(); + + // Offset value must be within representable range + // and must have correct alignment properties. + if (TII->isValidAutoIncImm(StoredVT, Val)) { + SDValue Ops[] = { Value, Base, + CurDAG->getTargetConstant(Val, MVT::i32), Chain}; + unsigned Opcode = 0; + + // Figure out the post inc version of opcode. + if (StoredVT == MVT::i64) Opcode = Hexagon::POST_STdri; + else if (StoredVT == MVT::i32) Opcode = Hexagon::POST_STwri; + else if (StoredVT == MVT::i16) Opcode = Hexagon::POST_SThri; + else if (StoredVT == MVT::i8) Opcode = Hexagon::POST_STbri; + else assert (0 && "unknown memory type"); + + // Build post increment store. + SDNode* Result = CurDAG->getMachineNode(Opcode, dl, MVT::i32, + MVT::Other, Ops, 4); + MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); + MemOp[0] = ST->getMemOperand(); + cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1); + + ReplaceUses(ST, Result); + ReplaceUses(SDValue(ST,1), SDValue(Result,1)); + return Result; + } + + // Note: Order of operands matches the def of instruction: + // def STrid : STInst<(outs), (ins MEMri:$addr, DoubleRegs:$src1), ... + // and it differs for POST_ST* for instance. + SDValue Ops[] = { Base, CurDAG->getTargetConstant(0, MVT::i32), Value, + Chain}; + unsigned Opcode = 0; + + // Figure out the opcode. + if (StoredVT == MVT::i64) Opcode = Hexagon::STrid; + else if (StoredVT == MVT::i32) Opcode = Hexagon::STriw; + else if (StoredVT == MVT::i16) Opcode = Hexagon::STrih; + else if (StoredVT == MVT::i8) Opcode = Hexagon::STrib; + else assert (0 && "unknown memory type"); + + // Build regular store. + SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32); + SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops, + 4); + // Build splitted incriment instruction. + SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32, + Base, + TargetConstVal, + SDValue(Result_1, 0)); + MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); + MemOp[0] = ST->getMemOperand(); + cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1); + + ReplaceUses(SDValue(ST,0), SDValue(Result_2,0)); + ReplaceUses(SDValue(ST,1), SDValue(Result_1,0)); + return Result_2; +} + + +SDNode *HexagonDAGToDAGISel::SelectBaseOffsetStore(StoreSDNode *ST, + DebugLoc dl) { + SDValue Chain = ST->getChain(); + SDNode* Const32 = ST->getBasePtr().getNode(); + SDValue Value = ST->getValue(); + unsigned Opcode = 0; + + // Try to lower stores of GlobalAdresses into indexed stores. Custom + // lowering for GlobalAddress nodes has already turned it into a + // CONST32. Avoid truncating stores for the moment. Post-inc stores + // do the same. Don't think there's a reason for it, so will file a + // bug to fix. + if ((Const32->getOpcode() == HexagonISD::CONST32) && + !(Value.getValueType() == MVT::i64 && ST->isTruncatingStore())) { + SDValue Base = Const32->getOperand(0); + if (Base.getOpcode() == ISD::TargetGlobalAddress) { + EVT StoredVT = ST->getMemoryVT(); + int64_t Offset = cast<GlobalAddressSDNode>(Base)->getOffset(); + if (Offset != 0 && OffsetFitsS11(StoredVT, Offset)) { + MVT PointerTy = TLI.getPointerTy(); + const GlobalValue* GV = + cast<GlobalAddressSDNode>(Base)->getGlobal(); + SDValue TargAddr = + CurDAG->getTargetGlobalAddress(GV, dl, PointerTy, 0); + SDNode* NewBase = CurDAG->getMachineNode(Hexagon::CONST32_set, + dl, PointerTy, + TargAddr); + + // Figure out base + offset opcode + if (StoredVT == MVT::i64) Opcode = Hexagon::STrid_indexed; + else if (StoredVT == MVT::i32) Opcode = Hexagon::STriw_indexed; + else if (StoredVT == MVT::i16) Opcode = Hexagon::STrih_indexed; + else if (StoredVT == MVT::i8) Opcode = Hexagon::STrib_indexed; + else assert (0 && "unknown memory type"); + + SDValue Ops[] = {SDValue(NewBase,0), + CurDAG->getTargetConstant(Offset,PointerTy), + Value, Chain}; + // build indexed store + SDNode* Result = CurDAG->getMachineNode(Opcode, dl, + MVT::Other, Ops, 4); + MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); + MemOp[0] = ST->getMemOperand(); + cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1); + ReplaceUses(ST, Result); + return Result; + } + } + } + + return SelectCode(ST); +} + + +SDNode *HexagonDAGToDAGISel::SelectStore(SDNode *N) { + DebugLoc dl = N->getDebugLoc(); + StoreSDNode *ST = cast<StoreSDNode>(N); + ISD::MemIndexedMode AM = ST->getAddressingMode(); + + // Handle indexed stores. + if (AM != ISD::UNINDEXED) { + return SelectIndexedStore(ST, dl); + } + + return SelectBaseOffsetStore(ST, dl); +} + +SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) { + DebugLoc dl = N->getDebugLoc(); + + // + // %conv.i = sext i32 %tmp1 to i64 + // %conv2.i = sext i32 %add to i64 + // %mul.i = mul nsw i64 %conv2.i, %conv.i + // + // --- match with the following --- + // + // %mul.i = mpy (%tmp1, %add) + // + + if (N->getValueType(0) == MVT::i64) { + // Shifting a i64 signed multiply. + SDValue MulOp0 = N->getOperand(0); + SDValue MulOp1 = N->getOperand(1); + + SDValue OP0; + SDValue OP1; + + // Handle sign_extend and sextload. + if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) { + SDValue Sext0 = MulOp0.getOperand(0); + if (Sext0.getNode()->getValueType(0) != MVT::i32) { + SelectCode(N); + } + + OP0 = Sext0; + } else if (MulOp0.getOpcode() == ISD::LOAD) { + LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode()); + if (LD->getMemoryVT() != MVT::i32 || + LD->getExtensionType() != ISD::SEXTLOAD || + LD->getAddressingMode() != ISD::UNINDEXED) { + SelectCode(N); + } + + SDValue Base = LD->getBasePtr(); + SDValue Chain = LD->getChain(); + SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); + OP0 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32, + MVT::Other, + LD->getBasePtr(), TargetConst0, + Chain), 0); + } else { + return SelectCode(N); + } + + // Same goes for the second operand. + if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) { + SDValue Sext1 = MulOp1.getOperand(0); + if (Sext1.getNode()->getValueType(0) != MVT::i32) { + return SelectCode(N); + } + + OP1 = Sext1; + } else if (MulOp1.getOpcode() == ISD::LOAD) { + LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode()); + if (LD->getMemoryVT() != MVT::i32 || + LD->getExtensionType() != ISD::SEXTLOAD || + LD->getAddressingMode() != ISD::UNINDEXED) { + return SelectCode(N); + } + + SDValue Base = LD->getBasePtr(); + SDValue Chain = LD->getChain(); + SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); + OP1 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32, + MVT::Other, + LD->getBasePtr(), TargetConst0, + Chain), 0); + } else { + return SelectCode(N); + } + + // Generate a mpy instruction. + SDNode *Result = CurDAG->getMachineNode(Hexagon::MPY64, dl, MVT::i64, + OP0, OP1); + ReplaceUses(N, Result); + return Result; + } + + return SelectCode(N); +} + + +SDNode *HexagonDAGToDAGISel::SelectSelect(SDNode *N) { + DebugLoc dl = N->getDebugLoc(); + SDValue N0 = N->getOperand(0); + if (N0.getOpcode() == ISD::SETCC) { + SDValue N00 = N0.getOperand(0); + if (N00.getOpcode() == ISD::SIGN_EXTEND_INREG) { + SDValue N000 = N00.getOperand(0); + SDValue N001 = N00.getOperand(1); + if (cast<VTSDNode>(N001)->getVT() == MVT::i16) { + SDValue N01 = N0.getOperand(1); + SDValue N02 = N0.getOperand(2); + + // Pattern: (select:i32 (setcc:i1 (sext_inreg:i32 IntRegs:i32:$src2, + // i16:Other),IntRegs:i32:$src1, SETLT:Other),IntRegs:i32:$src1, + // IntRegs:i32:$src2) + // Emits: (MAXh_rr:i32 IntRegs:i32:$src1, IntRegs:i32:$src2) + // Pattern complexity = 9 cost = 1 size = 0. + if (cast<CondCodeSDNode>(N02)->get() == ISD::SETLT) { + SDValue N1 = N->getOperand(1); + if (N01 == N1) { + SDValue N2 = N->getOperand(2); + if (N000 == N2 && + N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 && + N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) { + SDNode *SextNode = CurDAG->getMachineNode(Hexagon::SXTH, dl, + MVT::i32, N000); + SDNode *Result = CurDAG->getMachineNode(Hexagon::MAXw_rr, dl, + MVT::i32, + SDValue(SextNode, 0), + N1); + ReplaceUses(N, Result); + return Result; + } + } + } + + // Pattern: (select:i32 (setcc:i1 (sext_inreg:i32 IntRegs:i32:$src2, + // i16:Other), IntRegs:i32:$src1, SETGT:Other), IntRegs:i32:$src1, + // IntRegs:i32:$src2) + // Emits: (MINh_rr:i32 IntRegs:i32:$src1, IntRegs:i32:$src2) + // Pattern complexity = 9 cost = 1 size = 0. + if (cast<CondCodeSDNode>(N02)->get() == ISD::SETGT) { + SDValue N1 = N->getOperand(1); + if (N01 == N1) { + SDValue N2 = N->getOperand(2); + if (N000 == N2 && + N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 && + N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) { + SDNode *SextNode = CurDAG->getMachineNode(Hexagon::SXTH, dl, + MVT::i32, N000); + SDNode *Result = CurDAG->getMachineNode(Hexagon::MINw_rr, dl, + MVT::i32, + SDValue(SextNode, 0), + N1); + ReplaceUses(N, Result); + return Result; + } + } + } + } + } + } + + return SelectCode(N); +} + + +SDNode *HexagonDAGToDAGISel::SelectTruncate(SDNode *N) { + DebugLoc dl = N->getDebugLoc(); + SDValue Shift = N->getOperand(0); + + // + // %conv.i = sext i32 %tmp1 to i64 + // %conv2.i = sext i32 %add to i64 + // %mul.i = mul nsw i64 %conv2.i, %conv.i + // %shr5.i = lshr i64 %mul.i, 32 + // %conv3.i = trunc i64 %shr5.i to i32 + // + // --- match with the following --- + // + // %conv3.i = mpy (%tmp1, %add) + // + // Trunc to i32. + if (N->getValueType(0) == MVT::i32) { + // Trunc from i64. + if (Shift.getNode()->getValueType(0) == MVT::i64) { + // Trunc child is logical shift right. + if (Shift.getOpcode() != ISD::SRL) { + return SelectCode(N); + } + + SDValue ShiftOp0 = Shift.getOperand(0); + SDValue ShiftOp1 = Shift.getOperand(1); + + // Shift by const 32 + if (ShiftOp1.getOpcode() != ISD::Constant) { + return SelectCode(N); + } + + int32_t ShiftConst = + cast<ConstantSDNode>(ShiftOp1.getNode())->getSExtValue(); + if (ShiftConst != 32) { + return SelectCode(N); + } + + // Shifting a i64 signed multiply + SDValue Mul = ShiftOp0; + if (Mul.getOpcode() != ISD::MUL) { + return SelectCode(N); + } + + SDValue MulOp0 = Mul.getOperand(0); + SDValue MulOp1 = Mul.getOperand(1); + + SDValue OP0; + SDValue OP1; + + // Handle sign_extend and sextload + if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) { + SDValue Sext0 = MulOp0.getOperand(0); + if (Sext0.getNode()->getValueType(0) != MVT::i32) { + return SelectCode(N); + } + + OP0 = Sext0; + } else if (MulOp0.getOpcode() == ISD::LOAD) { + LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode()); + if (LD->getMemoryVT() != MVT::i32 || + LD->getExtensionType() != ISD::SEXTLOAD || + LD->getAddressingMode() != ISD::UNINDEXED) { + return SelectCode(N); + } + + SDValue Base = LD->getBasePtr(); + SDValue Chain = LD->getChain(); + SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); + OP0 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32, + MVT::Other, + LD->getBasePtr(), + TargetConst0, Chain), 0); + } else { + return SelectCode(N); + } + + // Same goes for the second operand. + if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) { + SDValue Sext1 = MulOp1.getOperand(0); + if (Sext1.getNode()->getValueType(0) != MVT::i32) + return SelectCode(N); + + OP1 = Sext1; + } else if (MulOp1.getOpcode() == ISD::LOAD) { + LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode()); + if (LD->getMemoryVT() != MVT::i32 || + LD->getExtensionType() != ISD::SEXTLOAD || + LD->getAddressingMode() != ISD::UNINDEXED) { + return SelectCode(N); + } + + SDValue Base = LD->getBasePtr(); + SDValue Chain = LD->getChain(); + SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); + OP1 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32, + MVT::Other, + LD->getBasePtr(), + TargetConst0, Chain), 0); + } else { + return SelectCode(N); + } + + // Generate a mpy instruction. + SDNode *Result = CurDAG->getMachineNode(Hexagon::MPY, dl, MVT::i32, + OP0, OP1); + ReplaceUses(N, Result); + return Result; + } + } + + return SelectCode(N); +} + + +SDNode *HexagonDAGToDAGISel::SelectSHL(SDNode *N) { + DebugLoc dl = N->getDebugLoc(); + if (N->getValueType(0) == MVT::i32) { + SDValue Shl_0 = N->getOperand(0); + SDValue Shl_1 = N->getOperand(1); + // RHS is const. + if (Shl_1.getOpcode() == ISD::Constant) { + if (Shl_0.getOpcode() == ISD::MUL) { + SDValue Mul_0 = Shl_0.getOperand(0); // Val + SDValue Mul_1 = Shl_0.getOperand(1); // Const + // RHS of mul is const. + if (Mul_1.getOpcode() == ISD::Constant) { + int32_t ShlConst = + cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue(); + int32_t MulConst = + cast<ConstantSDNode>(Mul_1.getNode())->getSExtValue(); + int32_t ValConst = MulConst << ShlConst; + SDValue Val = CurDAG->getTargetConstant(ValConst, + MVT::i32); + if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Val.getNode())) + if (isInt<9>(CN->getSExtValue())) { + SDNode* Result = + CurDAG->getMachineNode(Hexagon::MPYI_ri, dl, + MVT::i32, Mul_0, Val); + ReplaceUses(N, Result); + return Result; + } + + } + } else if (Shl_0.getOpcode() == ISD::SUB) { + SDValue Sub_0 = Shl_0.getOperand(0); // Const 0 + SDValue Sub_1 = Shl_0.getOperand(1); // Val + if (Sub_0.getOpcode() == ISD::Constant) { + int32_t SubConst = + cast<ConstantSDNode>(Sub_0.getNode())->getSExtValue(); + if (SubConst == 0) { + if (Sub_1.getOpcode() == ISD::SHL) { + SDValue Shl2_0 = Sub_1.getOperand(0); // Val + SDValue Shl2_1 = Sub_1.getOperand(1); // Const + if (Shl2_1.getOpcode() == ISD::Constant) { + int32_t ShlConst = + cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue(); + int32_t Shl2Const = + cast<ConstantSDNode>(Shl2_1.getNode())->getSExtValue(); + int32_t ValConst = 1 << (ShlConst+Shl2Const); + SDValue Val = CurDAG->getTargetConstant(-ValConst, MVT::i32); + if (ConstantSDNode *CN = + dyn_cast<ConstantSDNode>(Val.getNode())) + if (isInt<9>(CN->getSExtValue())) { + SDNode* Result = + CurDAG->getMachineNode(Hexagon::MPYI_ri, dl, MVT::i32, + Shl2_0, Val); + ReplaceUses(N, Result); + return Result; + } + } + } + } + } + } + } + } + return SelectCode(N); +} + + +// +// If there is an zero_extend followed an intrinsic in DAG (this means - the +// result of the intrinsic is predicate); convert the zero_extend to +// transfer instruction. +// +// Zero extend -> transfer is lowered here. Otherwise, zero_extend will be +// converted into a MUX as predicate registers defined as 1 bit in the +// compiler. Architecture defines them as 8-bit registers. +// We want to preserve all the lower 8-bits and, not just 1 LSB bit. +// +SDNode *HexagonDAGToDAGISel::SelectZeroExtend(SDNode *N) { + DebugLoc dl = N->getDebugLoc(); + SDNode *IsIntrinsic = N->getOperand(0).getNode(); + if ((IsIntrinsic->getOpcode() == ISD::INTRINSIC_WO_CHAIN)) { + unsigned ID = + cast<ConstantSDNode>(IsIntrinsic->getOperand(0))->getZExtValue(); + if (doesIntrinsicReturnPredicate(ID)) { + // Now we need to differentiate target data types. + if (N->getValueType(0) == MVT::i64) { + // Convert the zero_extend to Rs = Pd followed by COMBINE_rr(0,Rs). + SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); + SDNode *Result_1 = CurDAG->getMachineNode(Hexagon::TFR_RsPd, dl, + MVT::i32, + SDValue(IsIntrinsic, 0)); + SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl, + MVT::i32, + TargetConst0); + SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl, + MVT::i64, MVT::Other, + SDValue(Result_2, 0), + SDValue(Result_1, 0)); + ReplaceUses(N, Result_3); + return Result_3; + } + if (N->getValueType(0) == MVT::i32) { + // Convert the zero_extend to Rs = Pd + SDNode* RsPd = CurDAG->getMachineNode(Hexagon::TFR_RsPd, dl, + MVT::i32, + SDValue(IsIntrinsic, 0)); + ReplaceUses(N, RsPd); + return RsPd; + } + assert(0 && "Unexpected value type"); + } + } + return SelectCode(N); +} + + +// +// Checking for intrinsics which have predicate registers as operand(s) +// and lowering to the actual intrinsic. +// +SDNode *HexagonDAGToDAGISel::SelectIntrinsicWOChain(SDNode *N) { + DebugLoc dl = N->getDebugLoc(); + unsigned ID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue(); + unsigned IntrinsicWithPred = doesIntrinsicContainPredicate(ID); + + // We are concerned with only those intrinsics that have predicate registers + // as at least one of the operands. + if (IntrinsicWithPred) { + SmallVector<SDValue, 8> Ops; + const MCInstrDesc &MCID = TII->get(IntrinsicWithPred); + const TargetRegisterInfo *TRI = TM.getRegisterInfo(); + + // Iterate over all the operands of the intrinsics. + // For PredRegs, do the transfer. + // For Double/Int Regs, just preserve the value + // For immediates, lower it. + for (unsigned i = 1; i < N->getNumOperands(); ++i) { + SDNode *Arg = N->getOperand(i).getNode(); + const TargetRegisterClass *RC = TII->getRegClass(MCID, i, TRI); + + if (RC == Hexagon::IntRegsRegisterClass || + RC == Hexagon::DoubleRegsRegisterClass) { + Ops.push_back(SDValue(Arg, 0)); + } else if (RC == Hexagon::PredRegsRegisterClass) { + // Do the transfer. + SDNode *PdRs = CurDAG->getMachineNode(Hexagon::TFR_PdRs, dl, MVT::i1, + SDValue(Arg, 0)); + Ops.push_back(SDValue(PdRs,0)); + } else if (RC == NULL && (dyn_cast<ConstantSDNode>(Arg) != NULL)) { + // This is immediate operand. Lower it here making sure that we DO have + // const SDNode for immediate value. + int32_t Val = cast<ConstantSDNode>(Arg)->getSExtValue(); + SDValue SDVal = CurDAG->getTargetConstant(Val, MVT::i32); + Ops.push_back(SDVal); + } else { + assert(0 && "Unimplemented"); + } + } + EVT ReturnValueVT = N->getValueType(0); + SDNode *Result = CurDAG->getMachineNode(IntrinsicWithPred, dl, + ReturnValueVT, + Ops.data(), Ops.size()); + ReplaceUses(N, Result); + return Result; + } + return SelectCode(N); +} + + +// +// Map predicate true (encoded as -1 in LLVM) to a XOR. +// +SDNode *HexagonDAGToDAGISel::SelectConstant(SDNode *N) { + DebugLoc dl = N->getDebugLoc(); + if (N->getValueType(0) == MVT::i1) { + SDNode* Result; + int32_t Val = cast<ConstantSDNode>(N)->getSExtValue(); + if (Val == -1) { + unsigned NewIntReg = TM.getInstrInfo()->createVR(MF, MVT(MVT::i32)); + SDValue Reg = CurDAG->getRegister(NewIntReg, MVT::i32); + + // Create the IntReg = 1 node. + SDNode* IntRegTFR = + CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32, + CurDAG->getTargetConstant(0, MVT::i32)); + + // Pd = IntReg + SDNode* Pd = CurDAG->getMachineNode(Hexagon::TFR_PdRs, dl, MVT::i1, + SDValue(IntRegTFR, 0)); + + // not(Pd) + SDNode* NotPd = CurDAG->getMachineNode(Hexagon::NOT_pp, dl, MVT::i1, + SDValue(Pd, 0)); + + // xor(not(Pd)) + Result = CurDAG->getMachineNode(Hexagon::XOR_pp, dl, MVT::i1, + SDValue(Pd, 0), SDValue(NotPd, 0)); + + // We have just built: + // Rs = Pd + // Pd = xor(not(Pd), Pd) + + ReplaceUses(N, Result); + return Result; + } + } + + return SelectCode(N); +} + + +// +// Map add followed by a asr -> asr +=. +// +SDNode *HexagonDAGToDAGISel::SelectAdd(SDNode *N) { + DebugLoc dl = N->getDebugLoc(); + if (N->getValueType(0) != MVT::i32) { + return SelectCode(N); + } + // Identify nodes of the form: add(asr(...)). + SDNode* Src1 = N->getOperand(0).getNode(); + if (Src1->getOpcode() != ISD::SRA || !Src1->hasOneUse() + || Src1->getValueType(0) != MVT::i32) { + return SelectCode(N); + } + + // Build Rd = Rd' + asr(Rs, Rt). The machine constraints will ensure that + // Rd and Rd' are assigned to the same register + SDNode* Result = CurDAG->getMachineNode(Hexagon::ASR_rr_acc, dl, MVT::i32, + N->getOperand(1), + Src1->getOperand(0), + Src1->getOperand(1)); + ReplaceUses(N, Result); + + return Result; +} + + +SDNode *HexagonDAGToDAGISel::Select(SDNode *N) { + if (N->isMachineOpcode()) + return NULL; // Already selected. + + + switch (N->getOpcode()) { + case ISD::Constant: + return SelectConstant(N); + + case ISD::ADD: + return SelectAdd(N); + + case ISD::SHL: + return SelectSHL(N); + + case ISD::LOAD: + return SelectLoad(N); + + case ISD::STORE: + return SelectStore(N); + + case ISD::SELECT: + return SelectSelect(N); + + case ISD::TRUNCATE: + return SelectTruncate(N); + + case ISD::MUL: + return SelectMul(N); + + case ISD::ZERO_EXTEND: + return SelectZeroExtend(N); + + case ISD::INTRINSIC_WO_CHAIN: + return SelectIntrinsicWOChain(N); + } + + return SelectCode(N); +} + + +// +// Hexagon_TODO: Five functions for ADDRri?! Surely there must be a better way +// to define these instructions. +// +bool HexagonDAGToDAGISel::SelectADDRri(SDValue& Addr, SDValue &Base, + SDValue &Offset) { + if (Addr.getOpcode() == ISD::TargetExternalSymbol || + Addr.getOpcode() == ISD::TargetGlobalAddress) + return false; // Direct calls. + + if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); + Offset = CurDAG->getTargetConstant(0, MVT::i32); + return true; + } + Base = Addr; + Offset = CurDAG->getTargetConstant(0, MVT::i32); + return true; +} + + +bool HexagonDAGToDAGISel::SelectADDRriS11_0(SDValue& Addr, SDValue &Base, + SDValue &Offset) { + if (Addr.getOpcode() == ISD::TargetExternalSymbol || + Addr.getOpcode() == ISD::TargetGlobalAddress) + return false; // Direct calls. + + if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); + Offset = CurDAG->getTargetConstant(0, MVT::i32); + return (IsS11_0_Offset(Offset.getNode())); + } + Base = Addr; + Offset = CurDAG->getTargetConstant(0, MVT::i32); + return (IsS11_0_Offset(Offset.getNode())); +} + + +bool HexagonDAGToDAGISel::SelectADDRriS11_1(SDValue& Addr, SDValue &Base, + SDValue &Offset) { + if (Addr.getOpcode() == ISD::TargetExternalSymbol || + Addr.getOpcode() == ISD::TargetGlobalAddress) + return false; // Direct calls. + + if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); + Offset = CurDAG->getTargetConstant(0, MVT::i32); + return (IsS11_1_Offset(Offset.getNode())); + } + Base = Addr; + Offset = CurDAG->getTargetConstant(0, MVT::i32); + return (IsS11_1_Offset(Offset.getNode())); +} + + +bool HexagonDAGToDAGISel::SelectADDRriS11_2(SDValue& Addr, SDValue &Base, + SDValue &Offset) { + if (Addr.getOpcode() == ISD::TargetExternalSymbol || + Addr.getOpcode() == ISD::TargetGlobalAddress) + return false; // Direct calls. + + if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); + Offset = CurDAG->getTargetConstant(0, MVT::i32); + return (IsS11_2_Offset(Offset.getNode())); + } + Base = Addr; + Offset = CurDAG->getTargetConstant(0, MVT::i32); + return (IsS11_2_Offset(Offset.getNode())); +} + + +bool HexagonDAGToDAGISel::SelectADDRriU6_0(SDValue& Addr, SDValue &Base, + SDValue &Offset) { + if (Addr.getOpcode() == ISD::TargetExternalSymbol || + Addr.getOpcode() == ISD::TargetGlobalAddress) + return false; // Direct calls. + + if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); + Offset = CurDAG->getTargetConstant(0, MVT::i32); + return (IsU6_0_Offset(Offset.getNode())); + } + Base = Addr; + Offset = CurDAG->getTargetConstant(0, MVT::i32); + return (IsU6_0_Offset(Offset.getNode())); +} + + +bool HexagonDAGToDAGISel::SelectADDRriU6_1(SDValue& Addr, SDValue &Base, + SDValue &Offset) { + if (Addr.getOpcode() == ISD::TargetExternalSymbol || + Addr.getOpcode() == ISD::TargetGlobalAddress) + return false; // Direct calls. + + if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); + Offset = CurDAG->getTargetConstant(0, MVT::i32); + return (IsU6_1_Offset(Offset.getNode())); + } + Base = Addr; + Offset = CurDAG->getTargetConstant(0, MVT::i32); + return (IsU6_1_Offset(Offset.getNode())); +} + + +bool HexagonDAGToDAGISel::SelectADDRriU6_2(SDValue& Addr, SDValue &Base, + SDValue &Offset) { + if (Addr.getOpcode() == ISD::TargetExternalSymbol || + Addr.getOpcode() == ISD::TargetGlobalAddress) + return false; // Direct calls. + + if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); + Offset = CurDAG->getTargetConstant(0, MVT::i32); + return (IsU6_2_Offset(Offset.getNode())); + } + Base = Addr; + Offset = CurDAG->getTargetConstant(0, MVT::i32); + return (IsU6_2_Offset(Offset.getNode())); +} + + +bool HexagonDAGToDAGISel::SelectMEMriS11_2(SDValue& Addr, SDValue &Base, + SDValue &Offset) { + + if (Addr.getOpcode() != ISD::ADD) { + return(SelectADDRriS11_2(Addr, Base, Offset)); + } + + return SelectADDRriS11_2(Addr, Base, Offset); +} + + +bool HexagonDAGToDAGISel::SelectADDRriS11_3(SDValue& Addr, SDValue &Base, + SDValue &Offset) { + if (Addr.getOpcode() == ISD::TargetExternalSymbol || + Addr.getOpcode() == ISD::TargetGlobalAddress) + return false; // Direct calls. + + if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); + Offset = CurDAG->getTargetConstant(0, MVT::i32); + return (IsS11_3_Offset(Offset.getNode())); + } + Base = Addr; + Offset = CurDAG->getTargetConstant(0, MVT::i32); + return (IsS11_3_Offset(Offset.getNode())); +} + +bool HexagonDAGToDAGISel::SelectADDRrr(SDValue &Addr, SDValue &R1, + SDValue &R2) { + if (Addr.getOpcode() == ISD::FrameIndex) return false; + if (Addr.getOpcode() == ISD::TargetExternalSymbol || + Addr.getOpcode() == ISD::TargetGlobalAddress) + return false; // Direct calls. + + if (Addr.getOpcode() == ISD::ADD) { + if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) + if (isInt<13>(CN->getSExtValue())) + return false; // Let the reg+imm pattern catch this! + R1 = Addr.getOperand(0); + R2 = Addr.getOperand(1); + return true; + } + + R1 = Addr; + + return true; +} + + +// Handle generic address case. It is accessed from inlined asm =m constraints, +// which could have any kind of pointer. +bool HexagonDAGToDAGISel::SelectAddr(SDNode *Op, SDValue Addr, + SDValue &Base, SDValue &Offset) { + if (Addr.getOpcode() == ISD::TargetExternalSymbol || + Addr.getOpcode() == ISD::TargetGlobalAddress) + return false; // Direct calls. + + if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); + Offset = CurDAG->getTargetConstant(0, MVT::i32); + return true; + } + + if (Addr.getOpcode() == ISD::ADD) { + Base = Addr.getOperand(0); + Offset = Addr.getOperand(1); + return true; + } + + Base = Addr; + Offset = CurDAG->getTargetConstant(0, MVT::i32); + return true; +} + + +bool HexagonDAGToDAGISel:: +SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, + std::vector<SDValue> &OutOps) { + SDValue Op0, Op1; + + switch (ConstraintCode) { + case 'o': // Offsetable. + case 'v': // Not offsetable. + default: return true; + case 'm': // Memory. + if (!SelectAddr(Op.getNode(), Op, Op0, Op1)) + return true; + break; + } + + OutOps.push_back(Op0); + OutOps.push_back(Op1); + return false; +} diff --git a/lib/Target/Hexagon/HexagonISelLowering.cpp b/lib/Target/Hexagon/HexagonISelLowering.cpp new file mode 100644 index 0000000000..8d2d3fd8f6 --- /dev/null +++ b/lib/Target/Hexagon/HexagonISelLowering.cpp @@ -0,0 +1,1503 @@ +//===-- HexagonISelLowering.cpp - Hexagon DAG Lowering Implementation -----===// +// +// 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 interfaces that Hexagon uses to lower LLVM code +// into a selection DAG. +// +//===----------------------------------------------------------------------===// + +#include "HexagonISelLowering.h" +#include "HexagonTargetMachine.h" +#include "HexagonMachineFunctionInfo.h" +#include "HexagonTargetObjectFile.h" +#include "HexagonSubtarget.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/InlineAsm.h" +#include "llvm/GlobalVariable.h" +#include "llvm/GlobalAlias.h" +#include "llvm/Intrinsics.h" +#include "llvm/CallingConv.h" +#include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "HexagonMachineFunctionInfo.h" +#include "llvm/Support/CommandLine.h" + +const unsigned Hexagon_MAX_RET_SIZE = 64; +using namespace llvm; + +static cl::opt<bool> +EmitJumpTables("hexagon-emit-jump-tables", cl::init(true), cl::Hidden, + cl::desc("Control jump table emission on Hexagon target")); + +int NumNamedVarArgParams = -1; + +// Implement calling convention for Hexagon. +static bool +CC_Hexagon(unsigned ValNo, MVT ValVT, + MVT LocVT, CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State); + +static bool +CC_Hexagon32(unsigned ValNo, MVT ValVT, + MVT LocVT, CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State); + +static bool +CC_Hexagon64(unsigned ValNo, MVT ValVT, + MVT LocVT, CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State); + +static bool +RetCC_Hexagon(unsigned ValNo, MVT ValVT, + MVT LocVT, CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State); + +static bool +RetCC_Hexagon32(unsigned ValNo, MVT ValVT, + MVT LocVT, CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State); + +static bool +RetCC_Hexagon64(unsigned ValNo, MVT ValVT, + MVT LocVT, CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State); + +static bool +CC_Hexagon_VarArg (unsigned ValNo, MVT ValVT, + MVT LocVT, CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State) { + + // NumNamedVarArgParams can not be zero for a VarArg function. + assert ( (NumNamedVarArgParams > 0) && + "NumNamedVarArgParams is not bigger than zero."); + + if ( (int)ValNo < NumNamedVarArgParams ) { + // Deal with named arguments. + return CC_Hexagon(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State); + } + + // Deal with un-named arguments. + unsigned ofst; + if (ArgFlags.isByVal()) { + // If pass-by-value, the size allocated on stack is decided + // by ArgFlags.getByValSize(), not by the size of LocVT. + assert ((ArgFlags.getByValSize() > 8) && + "ByValSize must be bigger than 8 bytes"); + ofst = State.AllocateStack(ArgFlags.getByValSize(), 4); + State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo)); + return false; + } + if (LocVT == MVT::i32) { + ofst = State.AllocateStack(4, 4); + State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo)); + return false; + } + if (LocVT == MVT::i64) { + ofst = State.AllocateStack(8, 8); + State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo)); + return false; + } + llvm_unreachable(0); + + return true; +} + + +static bool +CC_Hexagon (unsigned ValNo, MVT ValVT, + MVT LocVT, CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State) { + + if (ArgFlags.isByVal()) { + // Passed on stack. + assert ((ArgFlags.getByValSize() > 8) && + "ByValSize must be bigger than 8 bytes"); + unsigned Offset = State.AllocateStack(ArgFlags.getByValSize(), 4); + State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); + return false; + } + + if (LocVT == MVT::i1 || LocVT == MVT::i8 || LocVT == MVT::i16) { + LocVT = MVT::i32; + ValVT = MVT::i32; + if (ArgFlags.isSExt()) + LocInfo = CCValAssign::SExt; + else if (ArgFlags.isZExt()) + LocInfo = CCValAssign::ZExt; + else + LocInfo = CCValAssign::AExt; + } + + if (LocVT == MVT::i32) { + if (!CC_Hexagon32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State)) + return false; + } + + if (LocVT == MVT::i64) { + if (!CC_Hexagon64(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State)) + return false; + } + + return true; // CC didn't match. +} + + +static bool CC_Hexagon32(unsigned ValNo, MVT ValVT, + MVT LocVT, CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State) { + + static const unsigned RegList[] = { + Hexagon::R0, Hexagon::R1, Hexagon::R2, Hexagon::R3, Hexagon::R4, + Hexagon::R5 + }; + if (unsigned Reg = State.AllocateReg(RegList, 6)) { + State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); + return false; + } + + unsigned Offset = State.AllocateStack(4, 4); + State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); + return false; +} + +static bool CC_Hexagon64(unsigned ValNo, MVT ValVT, + MVT LocVT, CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State) { + + if (unsigned Reg = State.AllocateReg(Hexagon::D0)) { + State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); + return false; + } + + static const unsigned RegList1[] = { + Hexagon::D1, Hexagon::D2 + }; + static const unsigned RegList2[] = { + Hexagon::R1, Hexagon::R3 + }; + if (unsigned Reg = State.AllocateReg(RegList1, RegList2, 2)) { + State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); + return false; + } + + unsigned Offset = State.AllocateStack(8, 8, Hexagon::D2); + State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); + return false; +} + +static bool RetCC_Hexagon(unsigned ValNo, MVT ValVT, + MVT LocVT, CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State) { + + + if (LocVT == MVT::i1 || + LocVT == MVT::i8 || + LocVT == MVT::i16) { + LocVT = MVT::i32; + ValVT = MVT::i32; + if (ArgFlags.isSExt()) + LocInfo = CCValAssign::SExt; + else if (ArgFlags.isZExt()) + LocInfo = CCValAssign::ZExt; + else + LocInfo = CCValAssign::AExt; + } + + if (LocVT == MVT::i32) { + if (!RetCC_Hexagon32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State)) + return false; + } + + if (LocVT == MVT::i64) { + if (!RetCC_Hexagon64(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State)) + return false; + } + + return true; // CC didn't match. +} + +static bool RetCC_Hexagon32(unsigned ValNo, MVT ValVT, + MVT LocVT, CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State) { + + if (LocVT == MVT::i32) { + if (unsigned Reg = State.AllocateReg(Hexagon::R0)) { + State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); + return false; + } + } + + unsigned Offset = State.AllocateStack(4, 4); + State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); + return false; +} + +static bool RetCC_Hexagon64(unsigned ValNo, MVT ValVT, + MVT LocVT, CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State) { + if (LocVT == MVT::i64) { + if (unsigned Reg = State.AllocateReg(Hexagon::D0)) { + State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); + return false; + } + } + + unsigned Offset = State.AllocateStack(8, 8); + State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); + return false; +} + +SDValue +HexagonTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) +const { + return SDValue(); +} + +/// CreateCopyOfByValArgument - Make a copy of an aggregate at address specified +/// by "Src" to address "Dst" of size "Size". Alignment information is +/// specified by the specific parameter attribute. The copy will be passed as +/// a byval function parameter. Sometimes what we are copying is the end of a +/// larger object, the part that does not fit in registers. +static SDValue +CreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain, + ISD::ArgFlagsTy Flags, SelectionDAG &DAG, + DebugLoc dl) { + + SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), MVT::i32); + return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getByValAlign(), + /*isVolatile=*/false, /*AlwaysInline=*/false, + MachinePointerInfo(), MachinePointerInfo()); +} + + +// LowerReturn - Lower ISD::RET. If a struct is larger than 8 bytes and is +// passed by value, the function prototype is modified to return void and +// the value is stored in memory pointed by a pointer passed by caller. +SDValue +HexagonTargetLowering::LowerReturn(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl<ISD::OutputArg> &Outs, + const SmallVectorImpl<SDValue> &OutVals, + DebugLoc dl, SelectionDAG &DAG) const { + + // CCValAssign - represent the assignment of the return value to locations. + SmallVector<CCValAssign, 16> RVLocs; + + // CCState - Info about the registers and stack slot. + CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), + getTargetMachine(), RVLocs, *DAG.getContext()); + + // Analyze return values of ISD::RET + CCInfo.AnalyzeReturn(Outs, RetCC_Hexagon); + + SDValue StackPtr = DAG.getRegister(TM.getRegisterInfo()->getStackRegister(), + MVT::i32); + + // If this is the first return lowered for this function, add the regs to the + // liveout set for the function. + if (DAG.getMachineFunction().getRegInfo().liveout_empty()) { + for (unsigned i = 0; i != RVLocs.size(); ++i) + if (RVLocs[i].isRegLoc()) + DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg()); + } + + SDValue Flag; + // Copy the result values into the output registers. + for (unsigned i = 0; i != RVLocs.size(); ++i) { + CCValAssign &VA = RVLocs[i]; + SDValue Ret = OutVals[i]; + ISD::ArgFlagsTy Flags = Outs[i].Flags; + + Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Flag); + + // Guarantee that all emitted copies are stuck together with flags. + Flag = Chain.getValue(1); + } + + if (Flag.getNode()) + return DAG.getNode(HexagonISD::RET_FLAG, dl, MVT::Other, Chain, Flag); + + return DAG.getNode(HexagonISD::RET_FLAG, dl, MVT::Other, Chain); +} + + + + +/// LowerCallResult - Lower the result values of an ISD::CALL into the +/// appropriate copies out of appropriate physical registers. This assumes that +/// Chain/InFlag are the input chain/flag to use, and that TheCall is the call +/// being lowered. Returns a SDNode with the same number of values as the +/// ISD::CALL. +SDValue +HexagonTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, + CallingConv::ID CallConv, bool isVarArg, + const + SmallVectorImpl<ISD::InputArg> &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl<SDValue> &InVals, + const SmallVectorImpl<SDValue> &OutVals, + SDValue Callee) const { + + // Assign locations to each value returned by this call. + SmallVector<CCValAssign, 16> RVLocs; + + CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), + getTargetMachine(), RVLocs, *DAG.getContext()); + + CCInfo.AnalyzeCallResult(Ins, RetCC_Hexagon); + + // Copy all of the result registers out of their specified physreg. + for (unsigned i = 0; i != RVLocs.size(); ++i) { + Chain = DAG.getCopyFromReg(Chain, dl, + RVLocs[i].getLocReg(), + RVLocs[i].getValVT(), InFlag).getValue(1); + InFlag = Chain.getValue(2); + InVals.push_back(Chain.getValue(0)); + } + + return Chain; +} + +/// LowerCall - Functions arguments are copied from virtual regs to +/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted. +SDValue +HexagonTargetLowering::LowerCall(SDValue Chain, SDValue Callee, + CallingConv::ID CallConv, bool isVarArg, + bool &isTailCall, + const SmallVectorImpl<ISD::OutputArg> &Outs, + const SmallVectorImpl<SDValue> &OutVals, + const SmallVectorImpl<ISD::InputArg> &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl<SDValue> &InVals) const { + + bool IsStructRet = (Outs.empty()) ? false : Outs[0].Flags.isSRet(); + + // Analyze operands of the call, assigning locations to each operand. + SmallVector<CCValAssign, 16> ArgLocs; + CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), + getTargetMachine(), ArgLocs, *DAG.getContext()); + + // Check for varargs. + NumNamedVarArgParams = -1; + if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Callee)) + { + const Function* CalleeFn = NULL; + Callee = DAG.getTargetGlobalAddress(GA->getGlobal(), dl, MVT::i32); + if ((CalleeFn = dyn_cast<Function>(GA->getGlobal()))) + { + // If a function has zero args and is a vararg function, that's + // disallowed so it must be an undeclared function. Do not assume + // varargs if the callee is undefined. + if (CalleeFn->isVarArg() && + CalleeFn->getFunctionType()->getNumParams() != 0) { + NumNamedVarArgParams = CalleeFn->getFunctionType()->getNumParams(); + } + } + } + + if (NumNamedVarArgParams > 0) + CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon_VarArg); + else + CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon); + + + if(isTailCall) { + bool StructAttrFlag = + DAG.getMachineFunction().getFunction()->hasStructRetAttr(); + isTailCall = IsEligibleForTailCallOptimization(Callee, CallConv, + isVarArg, IsStructRet, + StructAttrFlag, + Outs, OutVals, Ins, DAG); + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i){ + CCValAssign &VA = ArgLocs[i]; + if (VA.isMemLoc()) { + isTailCall = false; + break; + } + } + if (isTailCall) { + DEBUG(dbgs () << "Eligible for Tail Call\n"); + } else { + DEBUG(dbgs () << + "Argument must be passed on stack. Not eligible for Tail Call\n"); + } + } + // Get a count of how many bytes are to be pushed on the stack. + unsigned NumBytes = CCInfo.getNextStackOffset(); + SmallVector<std::pair<unsigned, SDValue>, 16> RegsToPass; + SmallVector<SDValue, 8> MemOpChains; + + SDValue StackPtr = + DAG.getCopyFromReg(Chain, dl, TM.getRegisterInfo()->getStackRegister(), + getPointerTy()); + + // Walk the register/memloc assignments, inserting copies/loads. + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + CCValAssign &VA = ArgLocs[i]; + SDValue Arg = OutVals[i]; + ISD::ArgFlagsTy Flags = Outs[i].Flags; + + // Promote the value if needed. + switch (VA.getLocInfo()) { + default: + // Loc info must be one of Full, SExt, ZExt, or AExt. + assert(0 && "Unknown loc info!"); + case CCValAssign::Full: + break; + case CCValAssign::SExt: + Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg); + break; + case CCValAssign::ZExt: + Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg); + break; + case CCValAssign::AExt: + Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg); + break; + } + + if (VA.isMemLoc()) { + unsigned LocMemOffset = VA.getLocMemOffset(); + SDValue PtrOff = DAG.getConstant(LocMemOffset, StackPtr.getValueType()); + PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); + + if (Flags.isByVal()) { + // The argument is a struct passed by value. According to LLVM, "Arg" + // is is pointer. + MemOpChains.push_back(CreateCopyOfByValArgument(Arg, PtrOff, Chain, + Flags, DAG, dl)); + } else { + // The argument is not passed by value. "Arg" is a buildin type. It is + // not a pointer. + MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, + MachinePointerInfo(),false, false, + 0)); + } + continue; + } + + // Arguments that can be passed on register must be kept at RegsToPass + // vector. + if (VA.isRegLoc()) { + RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); + } + } + + // Transform all store nodes into one single node because all store + // nodes are independent of each other. + if (!MemOpChains.empty()) { + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &MemOpChains[0], + MemOpChains.size()); + } + + if (!isTailCall) + Chain = DAG.getCALLSEQ_START(Chain, DAG.getConstant(NumBytes, + getPointerTy(), true)); + + // Build a sequence of copy-to-reg nodes chained together with token + // chain and flag operands which copy the outgoing args into registers. + // The InFlag in necessary since all emited instructions must be + // stuck together. + SDValue InFlag; + if (!isTailCall) { + for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { + Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, + RegsToPass[i].second, InFlag); + InFlag = Chain.getValue(1); + } + } + + // For tail calls lower the arguments to the 'real' stack slot. + if (isTailCall) { + // Force all the incoming stack arguments to be loaded from the stack + // before any new outgoing arguments are stored to the stack, because the + // outgoing stack slots may alias the incoming argument stack slots, and + // the alias isn't otherwise explicit. This is slightly more conservative + // than necessary, because it means that each store effectively depends + // on every argument instead of just those arguments it would clobber. + // + // Do not flag preceeding copytoreg stuff together with the following stuff. + InFlag = SDValue(); + for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { + Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, + RegsToPass[i].second, InFlag); + InFlag = Chain.getValue(1); + } + InFlag =SDValue(); + } + + // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every + // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol + // node so that legalize doesn't hack it. + if (flag_aligned_memcpy) { + const char *MemcpyName = + "__hexagon_memcpy_likely_aligned_min32bytes_mult8bytes"; + Callee = + DAG.getTargetExternalSymbol(MemcpyName, getPointerTy()); + flag_aligned_memcpy = false; + } else if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) { + Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, getPointerTy()); + } else if (ExternalSymbolSDNode *S = + dyn_cast<ExternalSymbolSDNode>(Callee)) { + Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy()); + } + + // Returns a chain & a flag for retval copy to use. + SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); + SmallVector<SDValue, 8> Ops; + Ops.push_back(Chain); + Ops.push_back(Callee); + + // Add argument registers to the end of the list so that they are + // known live into the call. + for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { + Ops.push_back(DAG.getRegister(RegsToPass[i].first, + RegsToPass[i].second.getValueType())); + } + + if (InFlag.getNode()) { + Ops.push_back(InFlag); + } + + if (isTailCall) + return DAG.getNode(HexagonISD::TC_RETURN, dl, NodeTys, &Ops[0], Ops.size()); + + Chain = DAG.getNode(HexagonISD::CALL, dl, NodeTys, &Ops[0], Ops.size()); + InFlag = Chain.getValue(1); + + // Create the CALLSEQ_END node. + Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumBytes, true), + DAG.getIntPtrConstant(0, true), InFlag); + InFlag = Chain.getValue(1); + + // Handle result values, copying them out of physregs into vregs that we + // return. + return LowerCallResult(Chain, InFlag, CallConv, isVarArg, Ins, dl, DAG, + InVals, OutVals, Callee); +} + +static bool getIndexedAddressParts(SDNode *Ptr, EVT VT, + bool isSEXTLoad, SDValue &Base, + SDValue &Offset, bool &isInc, + SelectionDAG &DAG) { + if (Ptr->getOpcode() != ISD::ADD) + return false; + + if (VT == MVT::i64 || VT == MVT::i32 || VT == MVT::i16 || VT == MVT::i8) { + isInc = (Ptr->getOpcode() == ISD::ADD); + Base = Ptr->getOperand(0); + Offset = Ptr->getOperand(1); + // Ensure that Offset is a constant. + return (isa<ConstantSDNode>(Offset)); + } + + return false; +} + +// TODO: Put this function along with the other isS* functions in +// HexagonISelDAGToDAG.cpp into a common file. Or better still, use the +// functions defined in HexagonImmediates.td. +static bool Is_PostInc_S4_Offset(SDNode * S, int ShiftAmount) { + ConstantSDNode *N = cast<ConstantSDNode>(S); + + // immS4 predicate - True if the immediate fits in a 4-bit sign extended. + // field. + int64_t v = (int64_t)N->getSExtValue(); + int64_t m = 0; + if (ShiftAmount > 0) { + m = v % ShiftAmount; + v = v >> ShiftAmount; + } + return (v <= 7) && (v >= -8) && (m == 0); +} + +/// getPostIndexedAddressParts - returns true by value, base pointer and +/// offset pointer and addressing mode by reference if this node can be +/// combined with a load / store to form a post-indexed load / store. +bool HexagonTargetLowering::getPostIndexedAddressParts(SDNode *N, SDNode *Op, + SDValue &Base, + SDValue &Offset, + ISD::MemIndexedMode &AM, + SelectionDAG &DAG) const +{ + EVT VT; + SDValue Ptr; + bool isSEXTLoad = false; + + if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) { + VT = LD->getMemoryVT(); + isSEXTLoad = LD->getExtensionType() == ISD::SEXTLOAD; + } else if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) { + VT = ST->getMemoryVT(); + if (ST->getValue().getValueType() == MVT::i64 && ST->isTruncatingStore()) { + return false; + } + } else { + return false; + } + + bool isInc; + bool isLegal = getIndexedAddressParts(Op, VT, isSEXTLoad, Base, Offset, + isInc, DAG); + // ShiftAmount = number of left-shifted bits in the Hexagon instruction. + int ShiftAmount = VT.getSizeInBits() / 16; + if (isLegal && Is_PostInc_S4_Offset(Offset.getNode(), ShiftAmount)) { + AM = isInc ? ISD::POST_INC : ISD::POST_DEC; + return true; + } + + return false; +} + +SDValue HexagonTargetLowering::LowerINLINEASM(SDValue Op, + SelectionDAG &DAG) const { + SDNode *Node = Op.getNode(); + MachineFunction &MF = DAG.getMachineFunction(); + HexagonMachineFunctionInfo *FuncInfo = + MF.getInfo<HexagonMachineFunctionInfo>(); + switch (Node->getOpcode()) { + case ISD::INLINEASM: { + unsigned NumOps = Node->getNumOperands(); + if (Node->getOperand(NumOps-1).getValueType() == MVT::Glue) + --NumOps; // Ignore the flag operand. + + for (unsigned i = InlineAsm::Op_FirstOperand; i != NumOps;) { + if (FuncInfo->hasClobberLR()) + break; + unsigned Flags = + cast<ConstantSDNode>(Node->getOperand(i))->getZExtValue(); + unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags); + ++i; // Skip the ID value. + + switch (InlineAsm::getKind(Flags)) { + default: llvm_unreachable("Bad flags!"); + case InlineAsm::Kind_RegDef: + case InlineAsm::Kind_RegUse: + case InlineAsm::Kind_Imm: + case InlineAsm::Kind_Clobber: + case InlineAsm::Kind_Mem: { + for (; NumVals; --NumVals, ++i) {} + break; + } + case InlineAsm::Kind_RegDefEarlyClobber: { + for (; NumVals; --NumVals, ++i) { + unsigned Reg = + cast<RegisterSDNode>(Node->getOperand(i))->getReg(); + + // Check it to be lr + if (Reg == TM.getRegisterInfo()->getRARegister()) { + FuncInfo->setHasClobberLR(true); + break; + } + } + break; + } + } + } + } + } // Node->getOpcode + return Op; +} + + +// +// Taken from the XCore backend. +// +SDValue HexagonTargetLowering:: +LowerBR_JT(SDValue Op, SelectionDAG &DAG) const +{ + SDValue Chain = Op.getOperand(0); + SDValue Table = Op.getOperand(1); + SDValue Index = Op.getOperand(2); + DebugLoc dl = Op.getDebugLoc(); + JumpTableSDNode *JT = cast<JumpTableSDNode>(Table); + unsigned JTI = JT->getIndex(); + MachineFunction &MF = DAG.getMachineFunction(); + const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo(); + SDValue TargetJT = DAG.getTargetJumpTable(JT->getIndex(), MVT::i32); + + // Mark all jump table targets as address taken. + const std::vector<MachineJumpTableEntry> &JTE = MJTI->getJumpTables(); + const std::vector<MachineBasicBlock*> &JTBBs = JTE[JTI].MBBs; + for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) { + MachineBasicBlock *MBB = JTBBs[i]; + MBB->setHasAddressTaken(); + // This line is needed to set the hasAddressTaken flag on the BasicBlock + // object. + BlockAddress::get(const_cast<BasicBlock *>(MBB->getBasicBlock())); + } + + SDValue JumpTableBase = DAG.getNode(HexagonISD::WrapperJT, dl, + getPointerTy(), TargetJT); + SDValue ShiftIndex = DAG.getNode(ISD::SHL, dl, MVT::i32, Index, + DAG.getConstant(2, MVT::i32)); + SDValue JTAddress = DAG.getNode(ISD::ADD, dl, MVT::i32, JumpTableBase, + ShiftIndex); + SDValue LoadTarget = DAG.getLoad(MVT::i32, dl, Chain, JTAddress, + MachinePointerInfo(), false, false, false, + 0); + return DAG.getNode(HexagonISD::BR_JT, dl, MVT::Other, Chain, LoadTarget); +} + + +SDValue +HexagonTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op, + SelectionDAG &DAG) const { + SDValue Chain = Op.getOperand(0); + SDValue Size = Op.getOperand(1); + DebugLoc dl = Op.getDebugLoc(); + + unsigned SPReg = getStackPointerRegisterToSaveRestore(); + + // Get a reference to the stack pointer. + SDValue StackPointer = DAG.getCopyFromReg(Chain, dl, SPReg, MVT::i32); + + // Subtract the dynamic size from the actual stack size to + // obtain the new stack size. + SDValue Sub = DAG.getNode(ISD::SUB, dl, MVT::i32, StackPointer, Size); + + // + // For Hexagon, the outgoing memory arguments area should be on top of the + // alloca area on the stack i.e., the outgoing memory arguments should be + // at a lower address than the alloca area. Move the alloca area down the + // stack by adding back the space reserved for outgoing arguments to SP + // here. + // + // We do not know what the size of the outgoing args is at this point. + // So, we add a pseudo instruction ADJDYNALLOC that will adjust the + // stack pointer. We patch this instruction with the correct, known + // offset in emitPrologue(). + // + // Use a placeholder immediate (zero) for now. This will be patched up + // by emitPrologue(). + SDValue ArgAdjust = DAG.getNode(HexagonISD::ADJDYNALLOC, dl, + MVT::i32, + Sub, + DAG.getConstant(0, MVT::i32)); + + // The Sub result contains the new stack start address, so it + // must be placed in the stack pointer register. + SDValue CopyChain = DAG.getCopyToReg(Chain, dl, + TM.getRegisterInfo()->getStackRegister(), + Sub); + + SDValue Ops[2] = { ArgAdjust, CopyChain }; + return DAG.getMergeValues(Ops, 2, dl); +} + +SDValue +HexagonTargetLowering::LowerFormalArguments(SDValue Chain, + CallingConv::ID CallConv, + bool isVarArg, + const + SmallVectorImpl<ISD::InputArg> &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl<SDValue> &InVals) +const { + + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + MachineRegisterInfo &RegInfo = MF.getRegInfo(); + HexagonMachineFunctionInfo *FuncInfo = + MF.getInfo<HexagonMachineFunctionInfo>(); + + + // Assign locations to all of the incoming arguments. + SmallVector<CCValAssign, 16> ArgLocs; + CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), + getTargetMachine(), ArgLocs, *DAG.getContext()); + + CCInfo.AnalyzeFormalArguments(Ins, CC_Hexagon); + + // For LLVM, in the case when returning a struct by value (>8byte), + // the first argument is a pointer that points to the location on caller's + // stack where the return value will be stored. For Hexagon, the location on + // caller's stack is passed only when the struct size is smaller than (and + // equal to) 8 bytes. If not, no address will be passed into callee and + // callee return the result direclty through R0/R1. + + SmallVector<SDValue, 4> MemOps; + + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + CCValAssign &VA = ArgLocs[i]; + ISD::ArgFlagsTy Flags = Ins[i].Flags; + unsigned ObjSize; + unsigned StackLocation; + int FI; + + if ( (VA.isRegLoc() && !Flags.isByVal()) + || (VA.isRegLoc() && Flags.isByVal() && Flags.getByValSize() > 8)) { + // Arguments passed in registers + // 1. int, long long, ptr args that get allocated in register. + // 2. Large struct that gets an register to put its address in. + EVT RegVT = VA.getLocVT(); + if (RegVT == MVT::i8 || RegVT == MVT::i16 || RegVT == MVT::i32) { + unsigned VReg = + RegInfo.createVirtualRegister(Hexagon::IntRegsRegisterClass); + RegInfo.addLiveIn(VA.getLocReg(), VReg); + InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT)); + } else if (RegVT == MVT::i64) { + unsigned VReg = + RegInfo.createVirtualRegister(Hexagon::DoubleRegsRegisterClass); + RegInfo.addLiveIn(VA.getLocReg(), VReg); + InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT)); + } else { + assert (0); + } + } else if (VA.isRegLoc() && Flags.isByVal() && Flags.getByValSize() <= 8) { + assert (0 && "ByValSize must be bigger than 8 bytes"); + } else { + // Sanity check. + assert(VA.isMemLoc()); + + if (Flags.isByVal()) { + // If it's a byval parameter, then we need to compute the + // "real" size, not the size of the pointer. + ObjSize = Flags.getByValSize(); + } else { + ObjSize = VA.getLocVT().getStoreSizeInBits() >> 3; + } + + StackLocation = HEXAGON_LRFP_SIZE + VA.getLocMemOffset(); + // Create the frame index object for this incoming parameter... + FI = MFI->CreateFixedObject(ObjSize, StackLocation, true); + + // Create the SelectionDAG nodes cordl, responding to a load + // from this parameter. + SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); + + if (Flags.isByVal()) { + // If it's a pass-by-value aggregate, then do not dereference the stack + // location. Instead, we should generate a reference to the stack + // location. + InVals.push_back(FIN); + } else { + InVals.push_back(DAG.getLoad(VA.getLocVT(), dl, Chain, FIN, + MachinePointerInfo(), false, false, + false, 0)); + } + } + } + + if (!MemOps.empty()) + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &MemOps[0], + MemOps.size()); + + if (isVarArg) { + // This will point to the next argument passed via stack. + int FrameIndex = MFI->CreateFixedObject(Hexagon_PointerSize, + HEXAGON_LRFP_SIZE + + CCInfo.getNextStackOffset(), + true); + FuncInfo->setVarArgsFrameIndex(FrameIndex); + } + + return Chain; +} + +SDValue +HexagonTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const { + // VASTART stores the address of the VarArgsFrameIndex slot into the + // memory location argument. + MachineFunction &MF = DAG.getMachineFunction(); + HexagonMachineFunctionInfo *QFI = MF.getInfo<HexagonMachineFunctionInfo>(); + SDValue Addr = DAG.getFrameIndex(QFI->getVarArgsFrameIndex(), MVT::i32); + const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); + return DAG.getStore(Op.getOperand(0), Op.getDebugLoc(), Addr, + Op.getOperand(1), MachinePointerInfo(SV), false, + false, 0); +} + +SDValue +HexagonTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const { + SDNode* OpNode = Op.getNode(); + + SDValue Cond = DAG.getNode(ISD::SETCC, Op.getDebugLoc(), MVT::i1, + Op.getOperand(2), Op.getOperand(3), + Op.getOperand(4)); + return DAG.getNode(ISD::SELECT, Op.getDebugLoc(), OpNode->getValueType(0), + Cond, Op.getOperand(0), + Op.getOperand(1)); +} + +SDValue +HexagonTargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const { + const TargetRegisterInfo *TRI = TM.getRegisterInfo(); + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + MFI->setReturnAddressIsTaken(true); + + EVT VT = Op.getValueType(); + DebugLoc dl = Op.getDebugLoc(); + unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); + if (Depth) { + SDValue FrameAddr = LowerFRAMEADDR(Op, DAG); + SDValue Offset = DAG.getConstant(4, MVT::i32); + return DAG.getLoad(VT, dl, DAG.getEntryNode(), + DAG.getNode(ISD::ADD, dl, VT, FrameAddr, Offset), + MachinePointerInfo(), false, false, false, 0); + } + + // Return LR, which contains the return address. Mark it an implicit live-in. + unsigned Reg = MF.addLiveIn(TRI->getRARegister(), getRegClassFor(MVT::i32)); + return DAG.getCopyFromReg(DAG.getEntryNode(), dl, Reg, VT); +} + +SDValue +HexagonTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { + const HexagonRegisterInfo *TRI = TM.getRegisterInfo(); + MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); + MFI->setFrameAddressIsTaken(true); + + EVT VT = Op.getValueType(); + DebugLoc dl = Op.getDebugLoc(); + unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); + SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, + TRI->getFrameRegister(), VT); + while (Depth--) + FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr, + MachinePointerInfo(), + false, false, false, 0); + return FrameAddr; +} + + +SDValue HexagonTargetLowering::LowerMEMBARRIER(SDValue Op, + SelectionDAG& DAG) const { + DebugLoc dl = Op.getDebugLoc(); + return DAG.getNode(HexagonISD::BARRIER, dl, MVT::Other, Op.getOperand(0)); +} + + +SDValue HexagonTargetLowering::LowerATOMIC_FENCE(SDValue Op, + SelectionDAG& DAG) const { + DebugLoc dl = Op.getDebugLoc(); + return DAG.getNode(HexagonISD::BARRIER, dl, MVT::Other, Op.getOperand(0)); +} + + +SDValue HexagonTargetLowering::LowerGLOBALADDRESS(SDValue Op, + SelectionDAG &DAG) const { + SDValue Result; + const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); + int64_t Offset = cast<GlobalAddressSDNode>(Op)->getOffset(); + DebugLoc dl = Op.getDebugLoc(); + Result = DAG.getTargetGlobalAddress(GV, dl, getPointerTy(), Offset); + + HexagonTargetObjectFile &TLOF = + (HexagonTargetObjectFile&)getObjFileLowering(); + if (TLOF.IsGlobalInSmallSection(GV, getTargetMachine())) { + return DAG.getNode(HexagonISD::CONST32_GP, dl, getPointerTy(), Result); + } + + return DAG.getNode(HexagonISD::CONST32, dl, getPointerTy(), Result); +} + +//===----------------------------------------------------------------------===// +// TargetLowering Implementation +//===----------------------------------------------------------------------===// + +HexagonTargetLowering::HexagonTargetLowering(HexagonTargetMachine + &targetmachine) + : TargetLowering(targetmachine, new HexagonTargetObjectFile()), + TM(targetmachine) { + + // Set up the register classes. + addRegisterClass(MVT::i32, Hexagon::IntRegsRegisterClass); + addRegisterClass(MVT::i64, Hexagon::DoubleRegsRegisterClass); + + addRegisterClass(MVT::i1, Hexagon::PredRegsRegisterClass); + + computeRegisterProperties(); + + // Align loop entry + setPrefLoopAlignment(4); + + // Limits for inline expansion of memcpy/memmove + maxStoresPerMemcpy = 6; + maxStoresPerMemmove = 6; + + // + // Library calls for unsupported operations + // + setLibcallName(RTLIB::OGT_F64, "__hexagon_gtdf2"); + + setLibcallName(RTLIB::SINTTOFP_I64_F64, "__hexagon_floatdidf"); + setLibcallName(RTLIB::SINTTOFP_I128_F64, "__hexagon_floattidf"); + setLibcallName(RTLIB::SINTTOFP_I128_F32, "__hexagon_floattisf"); + setLibcallName(RTLIB::UINTTOFP_I32_F32, "__hexagon_floatunsisf"); + setLibcallName(RTLIB::UINTTOFP_I64_F32, "__hexagon_floatundisf"); + setLibcallName(RTLIB::SINTTOFP_I64_F32, "__hexagon_floatdisf"); + setLibcallName(RTLIB::UINTTOFP_I64_F64, "__hexagon_floatundidf"); + + setLibcallName(RTLIB::FPTOUINT_F32_I32, "__hexagon_fixunssfsi"); + setLibcallName(RTLIB::FPTOUINT_F32_I64, "__hexagon_fixunssfdi"); + setLibcallName(RTLIB::FPTOUINT_F32_I128, "__hexagon_fixunssfti"); + + setLibcallName(RTLIB::FPTOUINT_F64_I32, "__hexagon_fixunsdfsi"); + setLibcallName(RTLIB::FPTOUINT_F64_I64, "__hexagon_fixunsdfdi"); + setLibcallName(RTLIB::FPTOUINT_F64_I128, "__hexagon_fixunsdfti"); + + setLibcallName(RTLIB::UINTTOFP_I32_F64, "__hexagon_floatunsidf"); + setLibcallName(RTLIB::FPTOSINT_F32_I64, "__hexagon_fixsfdi"); + setLibcallName(RTLIB::FPTOSINT_F32_I128, "__hexagon_fixsfti"); + setLibcallName(RTLIB::FPTOSINT_F64_I64, "__hexagon_fixdfdi"); + setLibcallName(RTLIB::FPTOSINT_F64_I128, "__hexagon_fixdfti"); + + setLibcallName(RTLIB::OGT_F64, "__hexagon_gtdf2"); + + setLibcallName(RTLIB::SDIV_I32, "__hexagon_divsi3"); + setOperationAction(ISD::SDIV, MVT::i32, Expand); + setLibcallName(RTLIB::SREM_I32, "__hexagon_umodsi3"); + setOperationAction(ISD::SREM, MVT::i32, Expand); + + setLibcallName(RTLIB::SDIV_I64, "__hexagon_divdi3"); + setOperationAction(ISD::SDIV, MVT::i64, Expand); + setLibcallName(RTLIB::SREM_I64, "__hexagon_moddi3"); + setOperationAction(ISD::SREM, MVT::i64, Expand); + + setLibcallName(RTLIB::UDIV_I32, "__hexagon_udivsi3"); + setOperationAction(ISD::UDIV, MVT::i32, Expand); + + setLibcallName(RTLIB::UDIV_I64, "__hexagon_udivdi3"); + setOperationAction(ISD::UDIV, MVT::i64, Expand); + + setLibcallName(RTLIB::UREM_I32, "__hexagon_umodsi3"); + setOperationAction(ISD::UREM, MVT::i32, Expand); + + setLibcallName(RTLIB::UREM_I64, "__hexagon_umoddi3"); + setOperationAction(ISD::UREM, MVT::i64, Expand); + + setLibcallName(RTLIB::DIV_F32, "__hexagon_divsf3"); + setOperationAction(ISD::FDIV, MVT::f32, Expand); + + setLibcallName(RTLIB::DIV_F64, "__hexagon_divdf3"); + setOperationAction(ISD::FDIV, MVT::f64, Expand); + + setLibcallName(RTLIB::FPEXT_F32_F64, "__hexagon_extendsfdf2"); + setOperationAction(ISD::FP_EXTEND, MVT::f32, Expand); + + setLibcallName(RTLIB::SINTTOFP_I32_F32, "__hexagon_floatsisf"); + setOperationAction(ISD::SINT_TO_FP, MVT::i32, Expand); + + setLibcallName(RTLIB::ADD_F64, "__hexagon_adddf3"); + setOperationAction(ISD::FADD, MVT::f64, Expand); + + setLibcallName(RTLIB::ADD_F32, "__hexagon_addsf3"); + setOperationAction(ISD::FADD, MVT::f32, Expand); + + setLibcallName(RTLIB::ADD_F32, "__hexagon_addsf3"); + setOperationAction(ISD::FADD, MVT::f32, Expand); + + setLibcallName(RTLIB::OEQ_F32, "__hexagon_eqsf2"); + setCondCodeAction(ISD::SETOEQ, MVT::f32, Expand); + + setLibcallName(RTLIB::FPTOSINT_F64_I32, "__hexagon_fixdfsi"); + setOperationAction(ISD::FP_TO_SINT, MVT::f64, Expand); + + setLibcallName(RTLIB::FPTOSINT_F32_I32, "__hexagon_fixsfsi"); + setOperationAction(ISD::FP_TO_SINT, MVT::f32, Expand); + + setLibcallName(RTLIB::SINTTOFP_I32_F64, "__hexagon_floatsidf"); + setOperationAction(ISD::SINT_TO_FP, MVT::i32, Expand); + + setLibcallName(RTLIB::OGE_F64, "__hexagon_gedf2"); + setCondCodeAction(ISD::SETOGE, MVT::f64, Expand); + + setLibcallName(RTLIB::OGE_F32, "__hexagon_gesf2"); + setCondCodeAction(ISD::SETOGE, MVT::f32, Expand); + + setLibcallName(RTLIB::OGT_F32, "__hexagon_gtsf2"); + setCondCodeAction(ISD::SETOGT, MVT::f32, Expand); + + setLibcallName(RTLIB::OLE_F64, "__hexagon_ledf2"); + setCondCodeAction(ISD::SETOLE, MVT::f64, Expand); + + setLibcallName(RTLIB::OLE_F32, "__hexagon_lesf2"); + setCondCodeAction(ISD::SETOLE, MVT::f32, Expand); + + setLibcallName(RTLIB::OLT_F64, "__hexagon_ltdf2"); + setCondCodeAction(ISD::SETOLT, MVT::f64, Expand); + + setLibcallName(RTLIB::OLT_F32, "__hexagon_ltsf2"); + setCondCodeAction(ISD::SETOLT, MVT::f32, Expand); + + setLibcallName(RTLIB::SREM_I32, "__hexagon_modsi3"); + setOperationAction(ISD::SREM, MVT::i32, Expand); + + setLibcallName(RTLIB::MUL_F64, "__hexagon_muldf3"); + setOperationAction(ISD::FMUL, MVT::f64, Expand); + + setLibcallName(RTLIB::MUL_F32, "__hexagon_mulsf3"); + setOperationAction(ISD::MUL, MVT::f32, Expand); + + setLibcallName(RTLIB::UNE_F64, "__hexagon_nedf2"); + setCondCodeAction(ISD::SETUNE, MVT::f64, Expand); + + setLibcallName(RTLIB::UNE_F32, "__hexagon_nesf2"); + + + setLibcallName(RTLIB::SUB_F64, "__hexagon_subdf3"); + setOperationAction(ISD::SUB, MVT::f64, Expand); + + setLibcallName(RTLIB::SUB_F32, "__hexagon_subsf3"); + setOperationAction(ISD::SUB, MVT::f32, Expand); + + setLibcallName(RTLIB::FPROUND_F64_F32, "__hexagon_truncdfsf2"); + setOperationAction(ISD::FP_ROUND, MVT::f64, Expand); + + setLibcallName(RTLIB::UO_F64, "__hexagon_unorddf2"); + setCondCodeAction(ISD::SETUO, MVT::f64, Expand); + + setLibcallName(RTLIB::O_F64, "__hexagon_unorddf2"); + setCondCodeAction(ISD::SETO, MVT::f64, Expand); + + setLibcallName(RTLIB::OEQ_F64, "__hexagon_eqdf2"); + setCondCodeAction(ISD::SETOEQ, MVT::f64, Expand); + + setLibcallName(RTLIB::O_F32, "__hexagon_unordsf2"); + setCondCodeAction(ISD::SETO, MVT::f32, Expand); + + setLibcallName(RTLIB::UO_F32, "__hexagon_unordsf2"); + setCondCodeAction(ISD::SETUO, MVT::f32, Expand); + + setIndexedLoadAction(ISD::POST_INC, MVT::i8, Legal); + setIndexedLoadAction(ISD::POST_INC, MVT::i16, Legal); + setIndexedLoadAction(ISD::POST_INC, MVT::i32, Legal); + setIndexedLoadAction(ISD::POST_INC, MVT::i64, Legal); + + setIndexedStoreAction(ISD::POST_INC, MVT::i8, Legal); + setIndexedStoreAction(ISD::POST_INC, MVT::i16, Legal); + setIndexedStoreAction(ISD::POST_INC, MVT::i32, Legal); + setIndexedStoreAction(ISD::POST_INC, MVT::i64, Legal); + + setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand); + + // Turn FP extload into load/fextend. + setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand); + // Hexagon has a i1 sign extending load. + setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Expand); + // Turn FP truncstore into trunc + store. + setTruncStoreAction(MVT::f64, MVT::f32, Expand); + + // Custom legalize GlobalAddress nodes into CONST32. + setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); + setOperationAction(ISD::GlobalAddress, MVT::i8, Custom); + // Truncate action? + setOperationAction(ISD::TRUNCATE, MVT::i64, Expand); + + // Hexagon doesn't have sext_inreg, replace them with shl/sra. + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1 , Expand); + + // Hexagon has no REM or DIVREM operations. + setOperationAction(ISD::UREM, MVT::i32, Expand); + setOperationAction(ISD::SREM, MVT::i32, Expand); + setOperationAction(ISD::SDIVREM, MVT::i32, Expand); + setOperationAction(ISD::UDIVREM, MVT::i32, Expand); + setOperationAction(ISD::SREM, MVT::i64, Expand); + setOperationAction(ISD::SDIVREM, MVT::i64, Expand); + setOperationAction(ISD::UDIVREM, MVT::i64, Expand); + + setOperationAction(ISD::BSWAP, MVT::i64, Expand); + + // Expand fp<->uint. + setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand); + setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand); + + // Hexagon has no select or setcc: expand to SELECT_CC. + setOperationAction(ISD::SELECT, MVT::f32, Expand); + setOperationAction(ISD::SELECT, MVT::f64, Expand); + + // Lower SELECT_CC to SETCC and SELECT. + setOperationAction(ISD::SELECT_CC, MVT::i32, Custom); + setOperationAction(ISD::SELECT_CC, MVT::i64, Custom); + // This is a workaround documented in DAGCombiner.cpp:2892 We don't + // support SELECT_CC on every type. + setOperationAction(ISD::SELECT_CC, MVT::Other, Expand); + + setOperationAction(ISD::BR_CC, MVT::Other, Expand); + setOperationAction(ISD::BRIND, MVT::Other, Expand); + if (EmitJumpTables) { + setOperationAction(ISD::BR_JT, MVT::Other, Custom); + } else { + setOperationAction(ISD::BR_JT, MVT::Other, Expand); + } + + setOperationAction(ISD::BR_CC, MVT::i32, Expand); + + setOperationAction(ISD::MEMBARRIER, MVT::Other, Custom); + setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom); + + setOperationAction(ISD::FSIN , MVT::f64, Expand); + setOperationAction(ISD::FCOS , MVT::f64, Expand); + setOperationAction(ISD::FREM , MVT::f64, Expand); + setOperationAction(ISD::FSIN , MVT::f32, Expand); + setOperationAction(ISD::FCOS , MVT::f32, Expand); + setOperationAction(ISD::FREM , MVT::f32, Expand); + setOperationAction(ISD::CTPOP, MVT::i32, Expand); + setOperationAction(ISD::CTTZ , MVT::i32, Expand); + setOperationAction(ISD::CTLZ , MVT::i32, Expand); + setOperationAction(ISD::ROTL , MVT::i32, Expand); + setOperationAction(ISD::ROTR , MVT::i32, Expand); + setOperationAction(ISD::BSWAP, MVT::i32, Expand); + setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand); + setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand); + setOperationAction(ISD::FPOW , MVT::f64, Expand); + setOperationAction(ISD::FPOW , MVT::f32, Expand); + + setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); + setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); + setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); + + setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); + setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand); + + setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand); + setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand); + + setOperationAction(ISD::EXCEPTIONADDR, MVT::i64, Expand); + setOperationAction(ISD::EHSELECTION, MVT::i64, Expand); + setOperationAction(ISD::EXCEPTIONADDR, MVT::i32, Expand); + setOperationAction(ISD::EHSELECTION, MVT::i32, Expand); + + setOperationAction(ISD::EH_RETURN, MVT::Other, Expand); + + if (TM.getSubtargetImpl()->isSubtargetV2()) { + setExceptionPointerRegister(Hexagon::R20); + setExceptionSelectorRegister(Hexagon::R21); + } else { + setExceptionPointerRegister(Hexagon::R0); + setExceptionSelectorRegister(Hexagon::R1); + } + + // VASTART needs to be custom lowered to use the VarArgsFrameIndex. + setOperationAction(ISD::VASTART , MVT::Other, Custom); + + // Use the default implementation. + setOperationAction(ISD::VAARG , MVT::Other, Expand); + setOperationAction(ISD::VACOPY , MVT::Other, Expand); + setOperationAction(ISD::VAEND , MVT::Other, Expand); + setOperationAction(ISD::STACKSAVE , MVT::Other, Expand); + setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand); + + + setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Custom); + setOperationAction(ISD::INLINEASM , MVT::Other, Custom); + + setMinFunctionAlignment(2); + + // Needed for DYNAMIC_STACKALLOC expansion. + unsigned StackRegister = TM.getRegisterInfo()->getStackRegister(); + setStackPointerRegisterToSaveRestore(StackRegister); +} + + +const char* +HexagonTargetLowering::getTargetNodeName(unsigned Opcode) const { + switch (Opcode) { + default: return 0; + case HexagonISD::CONST32: return "HexagonISD::CONST32"; + case HexagonISD::ADJDYNALLOC: return "HexagonISD::ADJDYNALLOC"; + case HexagonISD::CMPICC: return "HexagonISD::CMPICC"; + case HexagonISD::CMPFCC: return "HexagonISD::CMPFCC"; + case HexagonISD::BRICC: return "HexagonISD::BRICC"; + case HexagonISD::BRFCC: return "HexagonISD::BRFCC"; + case HexagonISD::SELECT_ICC: return "HexagonISD::SELECT_ICC"; + case HexagonISD::SELECT_FCC: return "HexagonISD::SELECT_FCC"; + case HexagonISD::Hi: return "HexagonISD::Hi"; + case HexagonISD::Lo: return "HexagonISD::Lo"; + case HexagonISD::FTOI: return "HexagonISD::FTOI"; + case HexagonISD::ITOF: return "HexagonISD::ITOF"; + case HexagonISD::CALL: return "HexagonISD::CALL"; + case HexagonISD::RET_FLAG: return "HexagonISD::RET_FLAG"; + case HexagonISD::BR_JT: return "HexagonISD::BR_JT"; + case HexagonISD::TC_RETURN: return "HexagonISD::TC_RETURN"; + } +} + +bool +HexagonTargetLowering::isTruncateFree(Type *Ty1, Type *Ty2) const { + EVT MTy1 = EVT::getEVT(Ty1); + EVT MTy2 = EVT::getEVT(Ty2); + if (!MTy1.isSimple() || !MTy2.isSimple()) { + return false; + } + return ((MTy1.getSimpleVT() == MVT::i64) && (MTy2.getSimpleVT() == MVT::i32)); +} + +bool HexagonTargetLowering::isTruncateFree(EVT VT1, EVT VT2) const { + if (!VT1.isSimple() || !VT2.isSimple()) { + return false; + } + return ((VT1.getSimpleVT() == MVT::i64) && (VT2.getSimpleVT() == MVT::i32)); +} + +SDValue +HexagonTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { + switch (Op.getOpcode()) { + default: assert(0 && "Should not custom lower this!"); + // Frame & Return address. Currently unimplemented. + case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG); + case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG); + case ISD::GlobalTLSAddress: + assert(0 && "TLS not implemented for Hexagon."); + case ISD::MEMBARRIER: return LowerMEMBARRIER(Op, DAG); + case ISD::ATOMIC_FENCE: return LowerATOMIC_FENCE(Op, DAG); + case ISD::GlobalAddress: return LowerGLOBALADDRESS(Op, DAG); + case ISD::VASTART: return LowerVASTART(Op, DAG); + case ISD::BR_JT: return LowerBR_JT(Op, DAG); + + case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG); + case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG); + case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG); + case ISD::INLINEASM: return LowerINLINEASM(Op, DAG); + + } +} + + + +//===----------------------------------------------------------------------===// +// Hexagon Scheduler Hooks +//===----------------------------------------------------------------------===// +MachineBasicBlock * +HexagonTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, + MachineBasicBlock *BB) +const { + switch (MI->getOpcode()) { + case Hexagon::ADJDYNALLOC: { + MachineFunction *MF = BB->getParent(); + HexagonMachineFunctionInfo *FuncInfo = + MF->getInfo<HexagonMachineFunctionInfo>(); + FuncInfo->addAllocaAdjustInst(MI); + return BB; + } + default: + assert(false && "Unexpected instr type to insert"); + } // switch + return NULL; +} + +//===----------------------------------------------------------------------===// +// Inline Assembly Support +//===----------------------------------------------------------------------===// + +std::pair<unsigned, const TargetRegisterClass*> +HexagonTargetLowering::getRegForInlineAsmConstraint(const + std::string &Constraint, + EVT VT) const { + if (Constraint.size() == 1) { + switch (Constraint[0]) { + case 'r': // R0-R31 + switch (VT.getSimpleVT().SimpleTy) { + default: + assert(0 && "getRegForInlineAsmConstraint Unhandled data type"); + case MVT::i32: + case MVT::i16: + case MVT::i8: + return std::make_pair(0U, Hexagon::IntRegsRegisterClass); + case MVT::i64: + return std::make_pair(0U, Hexagon::DoubleRegsRegisterClass); + } + default: + assert(0 && "Unknown asm register class"); + } + } + + return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); +} + +/// isLegalAddressingMode - Return true if the addressing mode represented by +/// AM is legal for this target, for a load/store of the specified type. +bool HexagonTargetLowering::isLegalAddressingMode(const AddrMode &AM, + Type *Ty) const { + // Allows a signed-extended 11-bit immediate field. + if (AM.BaseOffs <= -(1LL << 13) || AM.BaseOffs >= (1LL << 13)-1) { + return false; + } + + // No global is ever allowed as a base. + if (AM.BaseGV) { + return false; + } + + int Scale = AM.Scale; + if (Scale < 0) Scale = -Scale; + switch (Scale) { + case 0: // No scale reg, "r+i", "r", or just "i". + break; + default: // No scaled addressing mode. + return false; + } + return true; +} + +/// isLegalICmpImmediate - Return true if the specified immediate is legal +/// icmp immediate, that is the target has icmp instructions which can compare +/// a register against the immediate without having to materialize the +/// immediate into a register. +bool HexagonTargetLowering::isLegalICmpImmediate(int64_t Imm) const { + return Imm >= -512 && Imm <= 511; +} + +/// IsEligibleForTailCallOptimization - Check whether the call is eligible +/// for tail call optimization. Targets which want to do tail call +/// optimization should implement this function. +bool HexagonTargetLowering::IsEligibleForTailCallOptimization( + SDValue Callee, + CallingConv::ID CalleeCC, + bool isVarArg, + bool isCalleeStructRet, + bool isCallerStructRet, + const SmallVectorImpl<ISD::OutputArg> &Outs, + const SmallVectorImpl<SDValue> &OutVals, + const SmallVectorImpl<ISD::InputArg> &Ins, + SelectionDAG& DAG) const { + const Function *CallerF = DAG.getMachineFunction().getFunction(); + CallingConv::ID CallerCC = CallerF->getCallingConv(); + bool CCMatch = CallerCC == CalleeCC; + + // *************************************************************************** + // Look for obvious safe cases to perform tail call optimization that do not + // require ABI changes. + // *************************************************************************** + + // If this is a tail call via a function pointer, then don't do it! + if (!(dyn_cast<GlobalAddressSDNode>(Callee)) + && !(dyn_cast<ExternalSymbolSDNode>(Callee))) { + return false; + } + + // Do not optimize if the calling conventions do not match. + if (!CCMatch) + return false; + + // Do not tail call optimize vararg calls. + if (isVarArg) + return false; + + // Also avoid tail call optimization if either caller or callee uses struct + // return semantics. + if (isCalleeStructRet || isCallerStructRet) + return false; + + // In addition to the cases above, we also disable Tail Call Optimization if + // the calling convention code that at least one outgoing argument needs to + // go on the stack. We cannot check that here because at this point that + // information is not available. + return true; +} diff --git a/lib/Target/Hexagon/HexagonISelLowering.h b/lib/Target/Hexagon/HexagonISelLowering.h new file mode 100644 index 0000000000..b327615f8c --- /dev/null +++ b/lib/Target/Hexagon/HexagonISelLowering.h @@ -0,0 +1,162 @@ +//==-- HexagonISelLowering.h - Hexagon DAG Lowering Interface ----*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the interfaces that Hexagon uses to lower LLVM code into a +// selection DAG. +// +//===----------------------------------------------------------------------===// + +#ifndef Hexagon_ISELLOWERING_H +#define Hexagon_ISELLOWERING_H + +#include "llvm/Target/TargetLowering.h" +#include "llvm/CallingConv.h" +#include "llvm/CodeGen/CallingConvLower.h" +#include "Hexagon.h" + +namespace llvm { + namespace HexagonISD { + enum { + FIRST_NUMBER = ISD::BUILTIN_OP_END, + + CONST32, + CONST32_GP, // For marking data present in GP. + SETCC, + ADJDYNALLOC, + ARGEXTEND, + + CMPICC, // Compare two GPR operands, set icc. + CMPFCC, // Compare two FP operands, set fcc. + BRICC, // Branch to dest on icc condition + BRFCC, // Branch to dest on fcc condition + SELECT_ICC, // Select between two values using the current ICC flags. + SELECT_FCC, // Select between two values using the current FCC flags. + + Hi, Lo, // Hi/Lo operations, typically on a global address. + + FTOI, // FP to Int within a FP register. + ITOF, // Int to FP within a FP register. + + CALL, // A call instruction. + RET_FLAG, // Return with a flag operand. + BR_JT, // Jump table. + BARRIER, // Memory barrier. + WrapperJT, + TC_RETURN + }; + } + + class HexagonTargetLowering : public TargetLowering { + int VarArgsFrameOffset; // Frame offset to start of varargs area. + + bool CanReturnSmallStruct(const Function* CalleeFn, + unsigned& RetSize) const; + + public: + HexagonTargetMachine &TM; + explicit HexagonTargetLowering(HexagonTargetMachine &targetmachine); + + /// IsEligibleForTailCallOptimization - Check whether the call is eligible + /// for tail call optimization. Targets which want to do tail call + /// optimization should implement this function. + bool + IsEligibleForTailCallOptimization(SDValue Callee, + CallingConv::ID CalleeCC, + bool isVarArg, + bool isCalleeStructRet, + bool isCallerStructRet, + const + SmallVectorImpl<ISD::OutputArg> &Outs, + const SmallVectorImpl<SDValue> &OutVals, + const SmallVectorImpl<ISD::InputArg> &Ins, + SelectionDAG& DAG) const; + + virtual bool isTruncateFree(Type *Ty1, Type *Ty2) const; + virtual bool isTruncateFree(EVT VT1, EVT VT2) const; + + virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const; + + virtual const char *getTargetNodeName(unsigned Opcode) const; + SDValue LowerBR_JT(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerEH_LABEL(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerFormalArguments(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl<ISD::InputArg> &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl<SDValue> &InVals) const; + SDValue LowerGLOBALADDRESS(SDValue Op, SelectionDAG &DAG) const; + + SDValue LowerCall(SDValue Chain, SDValue Callee, + CallingConv::ID CallConv, bool isVarArg, + bool &isTailCall, + const SmallVectorImpl<ISD::OutputArg> &Outs, + const SmallVectorImpl<SDValue> &OutVals, + const SmallVectorImpl<ISD::InputArg> &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl<SDValue> &InVals) const; + + SDValue LowerCallResult(SDValue Chain, SDValue InFlag, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl<ISD::InputArg> &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl<SDValue> &InVals, + const SmallVectorImpl<SDValue> &OutVals, + SDValue Callee) const; + + SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerMEMBARRIER(SDValue Op, SelectionDAG& DAG) const; + SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG& DAG) const; + SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; + + SDValue LowerReturn(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl<ISD::OutputArg> &Outs, + const SmallVectorImpl<SDValue> &OutVals, + DebugLoc dl, SelectionDAG &DAG) const; + + virtual MachineBasicBlock + *EmitInstrWithCustomInserter(MachineInstr *MI, + MachineBasicBlock *BB) const; + + SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const; + virtual EVT getSetCCResultType(EVT VT) const { + return MVT::i1; + } + + virtual bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, + SDValue &Base, SDValue &Offset, + ISD::MemIndexedMode &AM, + SelectionDAG &DAG) const; + + std::pair<unsigned, const TargetRegisterClass*> + getRegForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const; + + // Intrinsics + virtual SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, + SelectionDAG &DAG) const; + /// isLegalAddressingMode - Return true if the addressing mode represented + /// by AM is legal for this target, for a load/store of the specified type. + /// The type may be VoidTy, in which case only return true if the addressing + /// mode is legal for a load/store of any legal type. + /// TODO: Handle pre/postinc as well. + virtual bool isLegalAddressingMode(const AddrMode &AM, Type *Ty) const; + + /// isLegalICmpImmediate - Return true if the specified immediate is legal + /// icmp immediate, that is the target has icmp instructions which can + /// compare a register against the immediate without having to materialize + /// the immediate into a register. + virtual bool isLegalICmpImmediate(int64_t Imm) const; + }; +} // end namespace llvm + +#endif // Hexagon_ISELLOWERING_H diff --git a/lib/Target/Hexagon/HexagonImmediates.td b/lib/Target/Hexagon/HexagonImmediates.td new file mode 100644 index 0000000000..1e3fcb862a --- /dev/null +++ b/lib/Target/Hexagon/HexagonImmediates.td @@ -0,0 +1,491 @@ +//=- HexagonImmediates.td - Hexagon immediate processing --*- tablegen -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illnois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// From IA64's InstrInfo file +def s32Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def s16Imm : Operand<i32> { + let PrintMethod = "printHexagonImmOperand"; +} + +def s12Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def s11Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def s11_0Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def s11_1Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def s11_2Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def s11_3Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def s10Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def s8Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def s9Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def s8Imm64 : Operand<i64> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def s6Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def s4Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def s4_0Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def s4_1Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def s4_2Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def s4_3Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def u64Imm : Operand<i64> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def u32Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def u16Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def u16_0Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def u16_1Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def u16_2Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def u11_3Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def u10Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def u9Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def u8Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def u7Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def u6Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def u6_0Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def u6_1Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def u6_2Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def u6_3Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def u5Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def u4Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def u3Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def u2Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def n8Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +def m6Imm : Operand<i32> { + // For now, we use a generic print function for all operands. + let PrintMethod = "printHexagonImmOperand"; +} + +// +// Immediate predicates +// +def s32ImmPred : PatLeaf<(i32 imm), [{ + // immS16 predicate - True if the immediate fits in a 16-bit sign extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isInt<32>(v); +}]>; + +def s32_24ImmPred : PatLeaf<(i32 imm), [{ + // s32_24ImmPred predicate - True if the immediate fits in a 32-bit sign + // extended field that is a multiple of 0x1000000. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedInt<32,24>(v); +}]>; + +def s32_16s8ImmPred : PatLeaf<(i32 imm), [{ + // s32_16s8ImmPred predicate - True if the immediate fits in a 32-bit sign + // extended field that is a multiple of 0x10000. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedInt<24,16>(v); +}]>; + +def s16ImmPred : PatLeaf<(i32 imm), [{ + // immS16 predicate - True if the immediate fits in a 16-bit sign extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isInt<16>(v); +}]>; + + +def s13ImmPred : PatLeaf<(i32 imm), [{ + // immS13 predicate - True if the immediate fits in a 13-bit sign extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isInt<13>(v); +}]>; + + +def s12ImmPred : PatLeaf<(i32 imm), [{ + // immS16 predicate - True if the immediate fits in a 16-bit sign extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isInt<12>(v); +}]>; + +def s11_0ImmPred : PatLeaf<(i32 imm), [{ + // immS16 predicate - True if the immediate fits in a 16-bit sign extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isInt<11>(v); +}]>; + + +def s11_1ImmPred : PatLeaf<(i32 imm), [{ + // immS16 predicate - True if the immediate fits in a 16-bit sign extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedInt<11,1>(v); +}]>; + + +def s11_2ImmPred : PatLeaf<(i32 imm), [{ + // immS16 predicate - True if the immediate fits in a 16-bit sign extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedInt<11,2>(v); +}]>; + + +def s11_3ImmPred : PatLeaf<(i32 imm), [{ + // immS16 predicate - True if the immediate fits in a 16-bit sign extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedInt<11,3>(v); +}]>; + + +def s10ImmPred : PatLeaf<(i32 imm), [{ + // s10ImmPred predicate - True if the immediate fits in a 10-bit sign extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isInt<10>(v); +}]>; + + +def s9ImmPred : PatLeaf<(i32 imm), [{ + // s9ImmPred predicate - True if the immediate fits in a 9-bit sign extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isInt<9>(v); +}]>; + + +def s8ImmPred : PatLeaf<(i32 imm), [{ + // s8ImmPred predicate - True if the immediate fits in a 8-bit sign extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isInt<8>(v); +}]>; + + +def s8Imm64Pred : PatLeaf<(i64 imm), [{ + // s8ImmPred predicate - True if the immediate fits in a 8-bit sign extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isInt<8>(v); +}]>; + + +def s6ImmPred : PatLeaf<(i32 imm), [{ + // s6ImmPred predicate - True if the immediate fits in a 6-bit sign extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isInt<6>(v); +}]>; + + +def s4_0ImmPred : PatLeaf<(i32 imm), [{ + // s4_0ImmPred predicate - True if the immediate fits in a 4-bit sign extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isInt<4>(v); +}]>; + + +def s4_1ImmPred : PatLeaf<(i32 imm), [{ + // s4_1ImmPred predicate - True if the immediate fits in a 4-bit sign extended + // field of 2. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedInt<4,1>(v); +}]>; + + +def s4_2ImmPred : PatLeaf<(i32 imm), [{ + // s4_2ImmPred predicate - True if the immediate fits in a 4-bit sign extended + // field that is a multiple of 4. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedInt<4,2>(v); +}]>; + + +def s4_3ImmPred : PatLeaf<(i32 imm), [{ + // s4_3ImmPred predicate - True if the immediate fits in a 4-bit sign extended + // field that is a multiple of 8. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedInt<4,3>(v); +}]>; + + +def u64ImmPred : PatLeaf<(i64 imm), [{ + // immS16 predicate - True if the immediate fits in a 16-bit sign extended + // field. + // Adding "N ||" to supress gcc unused warning. + return (N || true); +}]>; + +def u32ImmPred : PatLeaf<(i32 imm), [{ + // immS16 predicate - True if the immediate fits in a 16-bit sign extended + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isUInt<32>(v); +}]>; + +def u16ImmPred : PatLeaf<(i32 imm), [{ + // u16ImmPred predicate - True if the immediate fits in a 16-bit unsigned + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isUInt<16>(v); +}]>; + +def u16_s8ImmPred : PatLeaf<(i32 imm), [{ + // u16_s8ImmPred predicate - True if the immediate fits in a 16-bit sign + // extended s8 field. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedUInt<16,8>(v); +}]>; + +def u9ImmPred : PatLeaf<(i32 imm), [{ + // u9ImmPred predicate - True if the immediate fits in a 9-bit unsigned + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isUInt<9>(v); +}]>; + + +def u8ImmPred : PatLeaf<(i32 imm), [{ + // u8ImmPred predicate - True if the immediate fits in a 8-bit unsigned + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isUInt<8>(v); +}]>; + +def u7ImmPred : PatLeaf<(i32 imm), [{ + // u7ImmPred predicate - True if the immediate fits in a 8-bit unsigned + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isUInt<7>(v); +}]>; + + +def u6ImmPred : PatLeaf<(i32 imm), [{ + // u6ImmPred predicate - True if the immediate fits in a 6-bit unsigned + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isUInt<6>(v); +}]>; + +def u6_0ImmPred : PatLeaf<(i32 imm), [{ + // u6_0ImmPred predicate - True if the immediate fits in a 6-bit unsigned + // field. Same as u6ImmPred. + int64_t v = (int64_t)N->getSExtValue(); + return isUInt<6>(v); +}]>; + +def u6_1ImmPred : PatLeaf<(i32 imm), [{ + // u6_1ImmPred predicate - True if the immediate fits in a 6-bit unsigned + // field that is 1 bit alinged - multiple of 2. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedUInt<6,1>(v); +}]>; + +def u6_2ImmPred : PatLeaf<(i32 imm), [{ + // u6_2ImmPred predicate - True if the immediate fits in a 6-bit unsigned + // field that is 2 bits alinged - multiple of 4. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedUInt<6,2>(v); +}]>; + +def u6_3ImmPred : PatLeaf<(i32 imm), [{ + // u6_3ImmPred predicate - True if the immediate fits in a 6-bit unsigned + // field that is 3 bits alinged - multiple of 8. + int64_t v = (int64_t)N->getSExtValue(); + return isShiftedUInt<6,3>(v); +}]>; + +def u5ImmPred : PatLeaf<(i32 imm), [{ + // u5ImmPred predicate - True if the immediate fits in a 5-bit unsigned + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isUInt<5>(v); +}]>; + + +def u3ImmPred : PatLeaf<(i32 imm), [{ + // u3ImmPred predicate - True if the immediate fits in a 3-bit unsigned + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isUInt<3>(v); +}]>; + + +def u2ImmPred : PatLeaf<(i32 imm), [{ + // u2ImmPred predicate - True if the immediate fits in a 2-bit unsigned + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isUInt<2>(v); +}]>; + + +def u1ImmPred : PatLeaf<(i1 imm), [{ + // u1ImmPred predicate - True if the immediate fits in a 1-bit unsigned + // field. + int64_t v = (int64_t)N->getSExtValue(); + return isUInt<1>(v); +}]>; + +def m6ImmPred : PatLeaf<(i32 imm), [{ + // m6ImmPred predicate - True if the immediate is negative and fits in + // a 6-bit negative number. + int64_t v = (int64_t)N->getSExtValue(); + return isInt<6>(v); +}]>; + +//InN means negative integers in [-(2^N - 1), 0] +def n8ImmPred : PatLeaf<(i32 imm), [{ + // n8ImmPred predicate - True if the immediate fits in a 8-bit unsigned + // field. + int64_t v = (int64_t)N->getSExtValue(); + return (-255 <= v && v <= 0); +}]>; diff --git a/lib/Target/Hexagon/HexagonInstrFormats.td b/lib/Target/Hexagon/HexagonInstrFormats.td new file mode 100644 index 0000000000..7e9277655b --- /dev/null +++ b/lib/Target/Hexagon/HexagonInstrFormats.td @@ -0,0 +1,242 @@ +//==- HexagonInstrFormats.td - Hexagon Instruction Formats --*- tablegen -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +class InstHexagon<dag outs, dag ins, string asmstr, list<dag> pattern, + string cstr, + InstrItinClass itin> : Instruction { + field bits<32> Inst; + + let Namespace = "Hexagon"; + +/* Commented out for Hexagon + bits<2> op; + let Inst{31-30} = op; */ // Top two bits are the 'op' field + + dag OutOperandList = outs; + dag InOperandList = ins; + let AsmString = asmstr; + let Pattern = pattern; + let Constraints = cstr; + let Itinerary = itin; +} + +//----------------------------------------------------------------------------// +// Intruction Classes Definitions + +//----------------------------------------------------------------------------// + +// LD Instruction Class in V2/V3/V4. +// Definition of the instruction class NOT CHANGED. +class LDInst<dag outs, dag ins, string asmstr, list<dag> pattern> + : InstHexagon<outs, ins, asmstr, pattern, "", LD> { + bits<5> rd; + bits<5> rs; + bits<13> imm13; +} + +// LD Instruction Class in V2/V3/V4. +// Definition of the instruction class NOT CHANGED. +class LDInstPost<dag outs, dag ins, string asmstr, list<dag> pattern, + string cstr> + : InstHexagon<outs, ins, asmstr, pattern, cstr, LD> { + bits<5> rd; + bits<5> rs; + bits<5> rt; + bits<13> imm13; +} + +// ST Instruction Class in V2/V3 can take SLOT0 only. +// ST Instruction Class in V4 can take SLOT0 & SLOT1. +// Definition of the instruction class CHANGED from V2/V3 to V4. +class STInst<dag outs, dag ins, string asmstr, list<dag> pattern> + : InstHexagon<outs, ins, asmstr, pattern, "", ST> { + bits<5> rd; + bits<5> rs; + bits<13> imm13; +} + +// ST Instruction Class in V2/V3 can take SLOT0 only. +// ST Instruction Class in V4 can take SLOT0 & SLOT1. +// Definition of the instruction class CHANGED from V2/V3 to V4. +class STInstPost<dag outs, dag ins, string asmstr, list<dag> pattern, + string cstr> + : InstHexagon<outs, ins, asmstr, pattern, cstr, ST> { + bits<5> rd; + bits<5> rs; + bits<5> rt; + bits<13> imm13; +} + +// ALU32 Instruction Class in V2/V3/V4. +// Definition of the instruction class NOT CHANGED. +class ALU32Type<dag outs, dag ins, string asmstr, list<dag> pattern> + : InstHexagon<outs, ins, asmstr, pattern, "", ALU32> { + bits<5> rd; + bits<5> rs; + bits<5> rt; + bits<16> imm16; + bits<16> imm16_2; +} + +// ALU64 Instruction Class in V2/V3. +// XTYPE Instruction Class in V4. +// Definition of the instruction class NOT CHANGED. +// Name of the Instruction Class changed from ALU64 to XTYPE from V2/V3 to V4. +class ALU64Type<dag outs, dag ins, string asmstr, list<dag> pattern> + : InstHexagon<outs, ins, asmstr, pattern, "", ALU64> { + bits<5> rd; + bits<5> rs; + bits<5> rt; + bits<16> imm16; + bits<16> imm16_2; +} + +// M Instruction Class in V2/V3. +// XTYPE Instruction Class in V4. +// Definition of the instruction class NOT CHANGED. +// Name of the Instruction Class changed from M to XTYPE from V2/V3 to V4. +class MInst<dag outs, dag ins, string asmstr, list<dag> pattern> + : InstHexagon<outs, ins, asmstr, pattern, "", M> { + bits<5> rd; + bits<5> rs; + bits<5> rt; +} + +// M Instruction Class in V2/V3. +// XTYPE Instruction Class in V4. +// Definition of the instruction class NOT CHANGED. +// Name of the Instruction Class changed from M to XTYPE from V2/V3 to V4. +class MInst_acc<dag outs, dag ins, string asmstr, list<dag> pattern, + string cstr> + : InstHexagon<outs, ins, asmstr, pattern, cstr, M> { + bits<5> rd; + bits<5> rs; + bits<5> rt; +} + +// S Instruction Class in V2/V3. +// XTYPE Instruction Class in V4. +// Definition of the instruction class NOT CHANGED. +// Name of the Instruction Class changed from S to XTYPE from V2/V3 to V4. +class SInst<dag outs, dag ins, string asmstr, list<dag> pattern> +//: InstHexagon<outs, ins, asmstr, pattern, cstr, !if(V4T, XTYPE_V4, M)> { + : InstHexagon<outs, ins, asmstr, pattern, "", S> { +// : InstHexagon<outs, ins, asmstr, pattern, "", S> { + bits<5> rd; + bits<5> rs; + bits<5> rt; +} + +// S Instruction Class in V2/V3. +// XTYPE Instruction Class in V4. +// Definition of the instruction class NOT CHANGED. +// Name of the Instruction Class changed from S to XTYPE from V2/V3 to V4. +class SInst_acc<dag outs, dag ins, string asmstr, list<dag> pattern, + string cstr> + : InstHexagon<outs, ins, asmstr, pattern, cstr, S> { +// : InstHexagon<outs, ins, asmstr, pattern, cstr, S> { +// : InstHexagon<outs, ins, asmstr, pattern, cstr, !if(V4T, XTYPE_V4, S)> { + bits<5> rd; + bits<5> rs; + bits<5> rt; +} + +// J Instruction Class in V2/V3/V4. +// Definition of the instruction class NOT CHANGED. +class JType<dag outs, dag ins, string asmstr, list<dag> pattern> + : InstHexagon<outs, ins, asmstr, pattern, "", J> { + bits<16> imm16; +} + +// JR Instruction Class in V2/V3/V4. +// Definition of the instruction class NOT CHANGED. +class JRType<dag outs, dag ins, string asmstr, list<dag> pattern> + : InstHexagon<outs, ins, asmstr, pattern, "", JR> { + bits<5> rs; + bits<5> pu; // Predicate register +} + +// CR Instruction Class in V2/V3/V4. +// Definition of the instruction class NOT CHANGED. +class CRInst<dag outs, dag ins, string asmstr, list<dag> pattern> + : InstHexagon<outs, ins, asmstr, pattern, "", CR> { + bits<5> rs; + bits<10> imm10; +} + + +class Pseudo<dag outs, dag ins, string asmstr, list<dag> pattern> + : InstHexagon<outs, ins, asmstr, pattern, "", PSEUDO>; + + +//----------------------------------------------------------------------------// +// Intruction Classes Definitions - +//----------------------------------------------------------------------------// + + +// +// ALU32 patterns +//. +class ALU32_rr<dag outs, dag ins, string asmstr, list<dag> pattern> + : ALU32Type<outs, ins, asmstr, pattern> { +} + +class ALU32_ir<dag outs, dag ins, string asmstr, list<dag> pattern> + : ALU32Type<outs, ins, asmstr, pattern> { + let rt{0-4} = 0; +} + +class ALU32_ri<dag outs, dag ins, string asmstr, list<dag> pattern> + : ALU32Type<outs, ins, asmstr, pattern> { + let rt{0-4} = 0; +} + +class ALU32_ii<dag outs, dag ins, string asmstr, list<dag> pattern> + : ALU32Type<outs, ins, asmstr, pattern> { + let rt{0-4} = 0; +} + +// +// ALU64 patterns. +// +class ALU64_rr<dag outs, dag ins, string asmstr, list<dag> pattern> + : ALU64Type<outs, ins, asmstr, pattern> { +} + +// J Type Instructions. +class JInst<dag outs, dag ins, string asmstr, list<dag> pattern> + : JType<outs, ins, asmstr, pattern> { +} + +// JR type Instructions. +class JRInst<dag outs, dag ins, string asmstr, list<dag> pattern> + : JRType<outs, ins, asmstr, pattern> { +} + + +// Post increment ST Instruction. +class STInstPI<dag outs, dag ins, string asmstr, list<dag> pattern, string cstr> + : STInstPost<outs, ins, asmstr, pattern, cstr> { + let rt{0-4} = 0; +} + +// Post increment LD Instruction. +class LDInstPI<dag outs, dag ins, string asmstr, list<dag> pattern, string cstr> + : LDInstPost<outs, ins, asmstr, pattern, cstr> { + let rt{0-4} = 0; +} + +//===----------------------------------------------------------------------===// +// V4 Instruction Format Definitions + +//===----------------------------------------------------------------------===// + +include "HexagonInstrFormatsV4.td" + +//===----------------------------------------------------------------------===// +// V4 Instruction Format Definitions + +//===----------------------------------------------------------------------===// diff --git a/lib/Target/Hexagon/HexagonInstrFormatsV4.td b/lib/Target/Hexagon/HexagonInstrFormatsV4.td new file mode 100644 index 0000000000..bd5e4493d7 --- /dev/null +++ b/lib/Target/Hexagon/HexagonInstrFormatsV4.td @@ -0,0 +1,46 @@ +//==- HexagonInstrFormats.td - Hexagon Instruction Formats --*- tablegen -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the Hexagon V4 instruction classes in TableGen format. +// +//===----------------------------------------------------------------------===// + +// +// NV type instructions. +// +class NVInst_V4<dag outs, dag ins, string asmstr, list<dag> pattern> + : InstHexagon<outs, ins, asmstr, pattern, "", NV_V4> { + bits<5> rd; + bits<5> rs; + bits<13> imm13; +} + +// Definition of Post increment new value store. +class NVInstPost_V4<dag outs, dag ins, string asmstr, list<dag> pattern, + string cstr> + : InstHexagon<outs, ins, asmstr, pattern, cstr, NV_V4> { + bits<5> rd; + bits<5> rs; + bits<5> rt; + bits<13> imm13; +} + +// Post increment ST Instruction. +class NVInstPI_V4<dag outs, dag ins, string asmstr, list<dag> pattern, + string cstr> + : NVInstPost_V4<outs, ins, asmstr, pattern, cstr> { + let rt{0-4} = 0; +} + +class MEMInst_V4<dag outs, dag ins, string asmstr, list<dag> pattern> + : InstHexagon<outs, ins, asmstr, pattern, "", MEM_V4> { + bits<5> rd; + bits<5> rs; + bits<6> imm6; +} diff --git a/lib/Target/Hexagon/HexagonInstrInfo.cpp b/lib/Target/Hexagon/HexagonInstrInfo.cpp new file mode 100644 index 0000000000..2b480a3342 --- /dev/null +++ b/lib/Target/Hexagon/HexagonInstrInfo.cpp @@ -0,0 +1,1460 @@ +//=- HexagonInstrInfo.cpp - Hexagon Instruction Information -------*- 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 the Hexagon implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#include "HexagonRegisterInfo.h" +#include "HexagonInstrInfo.h" +#include "HexagonSubtarget.h" +#include "Hexagon.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#define GET_INSTRINFO_MC_DESC +#define GET_INSTRINFO_CTOR +#include "HexagonGenInstrInfo.inc" + +#include <iostream> + + +using namespace llvm; + +/// +/// Constants for Hexagon instructions. +/// +const int Hexagon_MEMW_OFFSET_MAX = 4095; +const int Hexagon_MEMW_OFFSET_MIN = 4096; +const int Hexagon_MEMD_OFFSET_MAX = 8191; +const int Hexagon_MEMD_OFFSET_MIN = 8192; +const int Hexagon_MEMH_OFFSET_MAX = 2047; +const int Hexagon_MEMH_OFFSET_MIN = 2048; +const int Hexagon_MEMB_OFFSET_MAX = 1023; +const int Hexagon_MEMB_OFFSET_MIN = 1024; +const int Hexagon_ADDI_OFFSET_MAX = 32767; +const int Hexagon_ADDI_OFFSET_MIN = 32768; +const int Hexagon_MEMD_AUTOINC_MAX = 56; +const int Hexagon_MEMD_AUTOINC_MIN = 64; +const int Hexagon_MEMW_AUTOINC_MAX = 28; +const int Hexagon_MEMW_AUTOINC_MIN = 32; +const int Hexagon_MEMH_AUTOINC_MAX = 14; +const int Hexagon_MEMH_AUTOINC_MIN = 16; +const int Hexagon_MEMB_AUTOINC_MAX = 7; +const int Hexagon_MEMB_AUTOINC_MIN = 8; + + + +HexagonInstrInfo::HexagonInstrInfo(HexagonSubtarget &ST) + : HexagonGenInstrInfo(Hexagon::ADJCALLSTACKDOWN, Hexagon::ADJCALLSTACKUP), + RI(ST, *this), Subtarget(ST) { +} + + +/// isLoadFromStackSlot - If the specified machine instruction is a direct +/// load from a stack slot, return the virtual or physical register number of +/// the destination along with the FrameIndex of the loaded stack slot. If +/// not, return 0. This predicate must return 0 if the instruction has +/// any side effects other than loading from the stack slot. +unsigned HexagonInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, + int &FrameIndex) const { + + + switch (MI->getOpcode()) { + case Hexagon::LDriw: + case Hexagon::LDrid: + case Hexagon::LDrih: + case Hexagon::LDrib: + case Hexagon::LDriub: + if (MI->getOperand(2).isFI() && + MI->getOperand(1).isImm() && (MI->getOperand(1).getImm() == 0)) { + FrameIndex = MI->getOperand(2).getIndex(); + return MI->getOperand(0).getReg(); + } + break; + + default: + break; + } + + return 0; +} + + +/// isStoreToStackSlot - If the specified machine instruction is a direct +/// store to a stack slot, return the virtual or physical register number of +/// the source reg along with the FrameIndex of the loaded stack slot. If +/// not, return 0. This predicate must return 0 if the instruction has +/// any side effects other than storing to the stack slot. +unsigned HexagonInstrInfo::isStoreToStackSlot(const MachineInstr *MI, + int &FrameIndex) const { + switch (MI->getOpcode()) { + case Hexagon::STriw: + case Hexagon::STrid: + case Hexagon::STrih: + case Hexagon::STrib: + if (MI->getOperand(2).isFI() && + MI->getOperand(1).isImm() && (MI->getOperand(1).getImm() == 0)) { + FrameIndex = MI->getOperand(2).getIndex(); + return MI->getOperand(0).getReg(); + } + break; + + default: + break; + } + + return 0; +} + + +unsigned +HexagonInstrInfo::InsertBranch(MachineBasicBlock &MBB,MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const SmallVectorImpl<MachineOperand> &Cond, + DebugLoc DL) const{ + + int BOpc = Hexagon::JMP; + int BccOpc = Hexagon::JMP_Pred; + + assert(TBB && "InsertBranch must not be told to insert a fallthrough"); + + int regPos = 0; + // Check if ReverseBranchCondition has asked to reverse this branch + // If we want to reverse the branch an odd number of times, we want + // JMP_PredNot. + if (!Cond.empty() && Cond[0].isImm() && Cond[0].getImm() == 0) { + BccOpc = Hexagon::JMP_PredNot; + regPos = 1; + } + + if (FBB == 0) { + if (Cond.empty()) { + // Due to a bug in TailMerging/CFG Optimization, we need to add a + // special case handling of a predicated jump followed by an + // unconditional jump. If not, Tail Merging and CFG Optimization go + // into an infinite loop. + MachineBasicBlock *NewTBB, *NewFBB; + SmallVector<MachineOperand, 4> Cond; + MachineInstr *Term = MBB.getFirstTerminator(); + if (isPredicated(Term) && !AnalyzeBranch(MBB, NewTBB, NewFBB, Cond, + false)) { + MachineBasicBlock *NextBB = + llvm::next(MachineFunction::iterator(&MBB)); + if (NewTBB == NextBB) { + ReverseBranchCondition(Cond); + RemoveBranch(MBB); + return InsertBranch(MBB, TBB, 0, Cond, DL); + } + } + BuildMI(&MBB, DL, get(BOpc)).addMBB(TBB); + } else { + BuildMI(&MBB, DL, + get(BccOpc)).addReg(Cond[regPos].getReg()).addMBB(TBB); + } + return 1; + } + + BuildMI(&MBB, DL, get(BccOpc)).addReg(Cond[regPos].getReg()).addMBB(TBB); + BuildMI(&MBB, DL, get(BOpc)).addMBB(FBB); + + return 2; +} + + +bool HexagonInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, + MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl<MachineOperand> &Cond, + bool AllowModify) const { + FBB = NULL; + + // If the block has no terminators, it just falls into the block after it. + MachineBasicBlock::iterator I = MBB.end(); + if (I == MBB.begin()) + return false; + + // A basic block may looks like this: + // + // [ insn + // EH_LABEL + // insn + // insn + // insn + // EH_LABEL + // insn ] + // + // It has two succs but does not have a terminator + // Don't know how to handle it. + do { + --I; + if (I->isEHLabel()) + return true; + } while (I != MBB.begin()); + + I = MBB.end(); + --I; + + while (I->isDebugValue()) { + if (I == MBB.begin()) + return false; + --I; + } + if (!isUnpredicatedTerminator(I)) + return false; + + // Get the last instruction in the block. + MachineInstr *LastInst = I; + + // If there is only one terminator instruction, process it. + if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) { + if (LastInst->getOpcode() == Hexagon::JMP) { + TBB = LastInst->getOperand(0).getMBB(); + return false; + } + if (LastInst->getOpcode() == Hexagon::JMP_Pred) { + // Block ends with fall-through true condbranch. + TBB = LastInst->getOperand(1).getMBB(); + Cond.push_back(LastInst->getOperand(0)); + return false; + } + if (LastInst->getOpcode() == Hexagon::JMP_PredNot) { + // Block ends with fall-through false condbranch. + TBB = LastInst->getOperand(1).getMBB(); + Cond.push_back(MachineOperand::CreateImm(0)); + Cond.push_back(LastInst->getOperand(0)); + return false; + } + // Otherwise, don't know what this is. + return true; + } + + // Get the instruction before it if it's a terminator. + MachineInstr *SecondLastInst = I; + + // If there are three terminators, we don't know what sort of block this is. + if (SecondLastInst && I != MBB.begin() && + isUnpredicatedTerminator(--I)) + return true; + + // If the block ends with Hexagon::BRCOND and Hexagon:JMP, handle it. + if (((SecondLastInst->getOpcode() == Hexagon::BRCOND) || + (SecondLastInst->getOpcode() == Hexagon::JMP_Pred)) && + LastInst->getOpcode() == Hexagon::JMP) { + TBB = SecondLastInst->getOperand(1).getMBB(); + Cond.push_back(SecondLastInst->getOperand(0)); + FBB = LastInst->getOperand(0).getMBB(); + return false; + } + + // If the block ends with Hexagon::JMP_PredNot and Hexagon:JMP, handle it. + if ((SecondLastInst->getOpcode() == Hexagon::JMP_PredNot) && + LastInst->getOpcode() == Hexagon::JMP) { + TBB = SecondLastInst->getOperand(1).getMBB(); + Cond.push_back(MachineOperand::CreateImm(0)); + Cond.push_back(SecondLastInst->getOperand(0)); + FBB = LastInst->getOperand(0).getMBB(); + return false; + } + + // If the block ends with two Hexagon:JMPs, handle it. The second one is not + // executed, so remove it. + if (SecondLastInst->getOpcode() == Hexagon::JMP && + LastInst->getOpcode() == Hexagon::JMP) { + TBB = SecondLastInst->getOperand(0).getMBB(); + I = LastInst; + if (AllowModify) + I->eraseFromParent(); + return false; + } + + // Otherwise, can't handle this. + return true; +} + + +unsigned HexagonInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { + int BOpc = Hexagon::JMP; + int BccOpc = Hexagon::JMP_Pred; + int BccOpcNot = Hexagon::JMP_PredNot; + + MachineBasicBlock::iterator I = MBB.end(); + if (I == MBB.begin()) return 0; + --I; + if (I->getOpcode() != BOpc && I->getOpcode() != BccOpc && + I->getOpcode() != BccOpcNot) + return 0; + + // Remove the branch. + I->eraseFromParent(); + + I = MBB.end(); + + if (I == MBB.begin()) return 1; + --I; + if (I->getOpcode() != BccOpc && I->getOpcode() != BccOpcNot) + return 1; + + // Remove the branch. + I->eraseFromParent(); + return 2; +} + + +void HexagonInstrInfo::copyPhysReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, DebugLoc DL, + unsigned DestReg, unsigned SrcReg, + bool KillSrc) const { + if (Hexagon::IntRegsRegClass.contains(SrcReg, DestReg)) { + BuildMI(MBB, I, DL, get(Hexagon::TFR), DestReg).addReg(SrcReg); + return; + } + if (Hexagon::DoubleRegsRegClass.contains(SrcReg, DestReg)) { + BuildMI(MBB, I, DL, get(Hexagon::TFR_64), DestReg).addReg(SrcReg); + return; + } + if (Hexagon::PredRegsRegClass.contains(SrcReg, DestReg)) { + // Map Pd = Ps to Pd = or(Ps, Ps). + BuildMI(MBB, I, DL, get(Hexagon::OR_pp), + DestReg).addReg(SrcReg).addReg(SrcReg); + return; + } + if (Hexagon::DoubleRegsRegClass.contains(DestReg, SrcReg)) { + // We can have an overlap between single and double reg: r1:0 = r0. + if(SrcReg == RI.getSubReg(DestReg, Hexagon::subreg_loreg)) { + // r1:0 = r0 + BuildMI(MBB, I, DL, get(Hexagon::TFRI), (RI.getSubReg(DestReg, + Hexagon::subreg_hireg))).addImm(0); + } else { + // r1:0 = r1 or no overlap. + BuildMI(MBB, I, DL, get(Hexagon::TFR), (RI.getSubReg(DestReg, + Hexagon::subreg_loreg))).addReg(SrcReg); + BuildMI(MBB, I, DL, get(Hexagon::TFRI), (RI.getSubReg(DestReg, + Hexagon::subreg_hireg))).addImm(0); + } + return; + } + if (Hexagon::CRRegsRegClass.contains(DestReg, SrcReg)) { + BuildMI(MBB, I, DL, get(Hexagon::TFCR), DestReg).addReg(SrcReg); + return; + } + + assert (0 && "Unimplemented"); +} + + +void HexagonInstrInfo:: +storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + unsigned SrcReg, bool isKill, int FI, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const { + + DebugLoc DL = MBB.findDebugLoc(I); + MachineFunction &MF = *MBB.getParent(); + MachineFrameInfo &MFI = *MF.getFrameInfo(); + unsigned Align = MFI.getObjectAlignment(FI); + + MachineMemOperand *MMO = + MF.getMachineMemOperand( + MachinePointerInfo(PseudoSourceValue::getFixedStack(FI)), + MachineMemOperand::MOStore, + MFI.getObjectSize(FI), + Align); + + if (Hexagon::IntRegsRegisterClass->hasSubClassEq(RC)) { + BuildMI(MBB, I, DL, get(Hexagon::STriw)) + .addFrameIndex(FI).addImm(0) + .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO); + } else if (Hexagon::DoubleRegsRegisterClass->hasSubClassEq(RC)) { + BuildMI(MBB, I, DL, get(Hexagon::STrid)) + .addFrameIndex(FI).addImm(0) + .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO); + } else if (Hexagon::PredRegsRegisterClass->hasSubClassEq(RC)) { + BuildMI(MBB, I, DL, get(Hexagon::STriw_pred)) + .addFrameIndex(FI).addImm(0) + .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO); + } else { + assert(0 && "Unimplemented"); + } +} + + +void HexagonInstrInfo::storeRegToAddr( + MachineFunction &MF, unsigned SrcReg, + bool isKill, + SmallVectorImpl<MachineOperand> &Addr, + const TargetRegisterClass *RC, + SmallVectorImpl<MachineInstr*> &NewMIs) const +{ + assert(0 && "Unimplemented"); + return; +} + + +void HexagonInstrInfo:: +loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + unsigned DestReg, int FI, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const { + DebugLoc DL = MBB.findDebugLoc(I); + MachineFunction &MF = *MBB.getParent(); + MachineFrameInfo &MFI = *MF.getFrameInfo(); + unsigned Align = MFI.getObjectAlignment(FI); + + MachineMemOperand *MMO = + MF.getMachineMemOperand( + MachinePointerInfo(PseudoSourceValue::getFixedStack(FI)), + MachineMemOperand::MOLoad, + MFI.getObjectSize(FI), + Align); + + if (RC == Hexagon::IntRegsRegisterClass) { + BuildMI(MBB, I, DL, get(Hexagon::LDriw), DestReg) + .addFrameIndex(FI).addImm(0).addMemOperand(MMO); + } else if (RC == Hexagon::DoubleRegsRegisterClass) { + BuildMI(MBB, I, DL, get(Hexagon::LDrid), DestReg) + .addFrameIndex(FI).addImm(0).addMemOperand(MMO); + } else if (RC == Hexagon::PredRegsRegisterClass) { + BuildMI(MBB, I, DL, get(Hexagon::LDriw_pred), DestReg) + .addFrameIndex(FI).addImm(0).addMemOperand(MMO); + } else { + assert(0 && "Can't store this register to stack slot"); + } +} + + +void HexagonInstrInfo::loadRegFromAddr(MachineFunction &MF, unsigned DestReg, + SmallVectorImpl<MachineOperand> &Addr, + const TargetRegisterClass *RC, + SmallVectorImpl<MachineInstr*> &NewMIs) const { + assert(0 && "Unimplemented"); +} + + +MachineInstr *HexagonInstrInfo::foldMemoryOperandImpl(MachineFunction &MF, + MachineInstr* MI, + const SmallVectorImpl<unsigned> &Ops, + int FI) const { + // Hexagon_TODO: Implement. + return(0); +} + + +unsigned HexagonInstrInfo::createVR(MachineFunction* MF, MVT VT) const { + + MachineRegisterInfo &RegInfo = MF->getRegInfo(); + const TargetRegisterClass *TRC; + if (VT == MVT::i1) { + TRC = Hexagon::PredRegsRegisterClass; + } else if (VT == MVT::i32) { + TRC = Hexagon::IntRegsRegisterClass; + } else if (VT == MVT::i64) { + TRC = Hexagon::DoubleRegsRegisterClass; + } else { + assert(0 && "Cannot handle this register class"); + } + + unsigned NewReg = RegInfo.createVirtualRegister(TRC); + return NewReg; +} + + +bool HexagonInstrInfo::isPredicable(MachineInstr *MI) const { + bool isPred = MI->getDesc().isPredicable(); + + if (!isPred) + return false; + + const int Opc = MI->getOpcode(); + + switch(Opc) { + case Hexagon::TFRI: + return isInt<12>(MI->getOperand(1).getImm()); + + case Hexagon::STrid: + case Hexagon::STrid_indexed: + return isShiftedUInt<6,3>(MI->getOperand(1).getImm()); + + case Hexagon::STriw: + case Hexagon::STriw_indexed: + case Hexagon::STriw_nv_V4: + return isShiftedUInt<6,2>(MI->getOperand(1).getImm()); + + case Hexagon::STrih: + case Hexagon::STrih_indexed: + case Hexagon::STrih_nv_V4: + return isShiftedUInt<6,1>(MI->getOperand(1).getImm()); + + case Hexagon::STrib: + case Hexagon::STrib_indexed: + case Hexagon::STrib_nv_V4: + return isUInt<6>(MI->getOperand(1).getImm()); + + case Hexagon::LDrid: + case Hexagon::LDrid_indexed: + return isShiftedUInt<6,3>(MI->getOperand(2).getImm()); + + case Hexagon::LDriw: + case Hexagon::LDriw_indexed: + return isShiftedUInt<6,2>(MI->getOperand(2).getImm()); + + case Hexagon::LDrih: + case Hexagon::LDriuh: + case Hexagon::LDrih_indexed: + case Hexagon::LDriuh_indexed: + return isShiftedUInt<6,1>(MI->getOperand(2).getImm()); + + case Hexagon::LDrib: + case Hexagon::LDriub: + case Hexagon::LDrib_indexed: + case Hexagon::LDriub_indexed: + return isUInt<6>(MI->getOperand(2).getImm()); + + case Hexagon::POST_LDrid: + return isShiftedInt<4,3>(MI->getOperand(3).getImm()); + + case Hexagon::POST_LDriw: + return isShiftedInt<4,2>(MI->getOperand(3).getImm()); + + case Hexagon::POST_LDrih: + case Hexagon::POST_LDriuh: + return isShiftedInt<4,1>(MI->getOperand(3).getImm()); + + case Hexagon::POST_LDrib: + case Hexagon::POST_LDriub: + return isInt<4>(MI->getOperand(3).getImm()); + + case Hexagon::STrib_imm_V4: + case Hexagon::STrih_imm_V4: + case Hexagon::STriw_imm_V4: + return (isUInt<6>(MI->getOperand(1).getImm()) && + isInt<6>(MI->getOperand(2).getImm())); + + case Hexagon::ADD_ri: + return isInt<8>(MI->getOperand(2).getImm()); + + case Hexagon::ASLH: + case Hexagon::ASRH: + case Hexagon::SXTB: + case Hexagon::SXTH: + case Hexagon::ZXTB: + case Hexagon::ZXTH: + return Subtarget.getHexagonArchVersion() == HexagonSubtarget::V4; + + case Hexagon::JMPR: + return false; + return true; + + default: + return true; + } + + return true; +} + + +int HexagonInstrInfo:: +getMatchingCondBranchOpcode(int Opc, bool invertPredicate) const { + switch(Opc) { + case Hexagon::TFR: + return !invertPredicate ? Hexagon::TFR_cPt : + Hexagon::TFR_cNotPt; + case Hexagon::TFRI: + return !invertPredicate ? Hexagon::TFRI_cPt : + Hexagon::TFRI_cNotPt; + case Hexagon::JMP: + return !invertPredicate ? Hexagon::JMP_Pred : + Hexagon::JMP_PredNot; + case Hexagon::ADD_ri: + return !invertPredicate ? Hexagon::ADD_ri_cPt : + Hexagon::ADD_ri_cNotPt; + case Hexagon::ADD_rr: + return !invertPredicate ? Hexagon::ADD_rr_cPt : + Hexagon::ADD_rr_cNotPt; + case Hexagon::XOR_rr: + return !invertPredicate ? Hexagon::XOR_rr_cPt : + Hexagon::XOR_rr_cNotPt; + case Hexagon::AND_rr: + return !invertPredicate ? Hexagon::AND_rr_cPt : + Hexagon::AND_rr_cNotPt; + case Hexagon::OR_rr: + return !invertPredicate ? Hexagon::OR_rr_cPt : + Hexagon::OR_rr_cNotPt; + case Hexagon::SUB_rr: + return !invertPredicate ? Hexagon::SUB_rr_cPt : + Hexagon::SUB_rr_cNotPt; + case Hexagon::COMBINE_rr: + return !invertPredicate ? Hexagon::COMBINE_rr_cPt : + Hexagon::COMBINE_rr_cNotPt; + case Hexagon::ASLH: + return !invertPredicate ? Hexagon::ASLH_cPt_V4 : + Hexagon::ASLH_cNotPt_V4; + case Hexagon::ASRH: + return !invertPredicate ? Hexagon::ASRH_cPt_V4 : + Hexagon::ASRH_cNotPt_V4; + case Hexagon::SXTB: + return !invertPredicate ? Hexagon::SXTB_cPt_V4 : + Hexagon::SXTB_cNotPt_V4; + case Hexagon::SXTH: + return !invertPredicate ? Hexagon::SXTH_cPt_V4 : + Hexagon::SXTH_cNotPt_V4; + case Hexagon::ZXTB: + return !invertPredicate ? Hexagon::ZXTB_cPt_V4 : + Hexagon::ZXTB_cNotPt_V4; + case Hexagon::ZXTH: + return !invertPredicate ? Hexagon::ZXTH_cPt_V4 : + Hexagon::ZXTH_cNotPt_V4; + + case Hexagon::JMPR: + return !invertPredicate ? Hexagon::JMPR_cPt : + Hexagon::JMPR_cNotPt; + + // V4 indexed+scaled load. + case Hexagon::LDrid_indexed_V4: + return !invertPredicate ? Hexagon::LDrid_indexed_cPt_V4 : + Hexagon::LDrid_indexed_cNotPt_V4; + case Hexagon::LDrid_indexed_shl_V4: + return !invertPredicate ? Hexagon::LDrid_indexed_shl_cPt_V4 : + Hexagon::LDrid_indexed_shl_cNotPt_V4; + case Hexagon::LDrib_indexed_V4: + return !invertPredicate ? Hexagon::LDrib_indexed_cPt_V4 : + Hexagon::LDrib_indexed_cNotPt_V4; + case Hexagon::LDriub_indexed_V4: + return !invertPredicate ? Hexagon::LDriub_indexed_cPt_V4 : + Hexagon::LDriub_indexed_cNotPt_V4; + case Hexagon::LDriub_ae_indexed_V4: + return !invertPredicate ? Hexagon::LDriub_indexed_cPt_V4 : + Hexagon::LDriub_indexed_cNotPt_V4; + case Hexagon::LDrib_indexed_shl_V4: + return !invertPredicate ? Hexagon::LDrib_indexed_shl_cPt_V4 : + Hexagon::LDrib_indexed_shl_cNotPt_V4; + case Hexagon::LDriub_indexed_shl_V4: + return !invertPredicate ? Hexagon::LDriub_indexed_shl_cPt_V4 : + Hexagon::LDriub_indexed_shl_cNotPt_V4; + case Hexagon::LDriub_ae_indexed_shl_V4: + return !invertPredicate ? Hexagon::LDriub_indexed_shl_cPt_V4 : + Hexagon::LDriub_indexed_shl_cNotPt_V4; + case Hexagon::LDrih_indexed_V4: + return !invertPredicate ? Hexagon::LDrih_indexed_cPt_V4 : + Hexagon::LDrih_indexed_cNotPt_V4; + case Hexagon::LDriuh_indexed_V4: + return !invertPredicate ? Hexagon::LDriuh_indexed_cPt_V4 : + Hexagon::LDriuh_indexed_cNotPt_V4; + case Hexagon::LDriuh_ae_indexed_V4: + return !invertPredicate ? Hexagon::LDriuh_indexed_cPt_V4 : + Hexagon::LDriuh_indexed_cNotPt_V4; + case Hexagon::LDrih_indexed_shl_V4: + return !invertPredicate ? Hexagon::LDrih_indexed_shl_cPt_V4 : + Hexagon::LDrih_indexed_shl_cNotPt_V4; + case Hexagon::LDriuh_indexed_shl_V4: + return !invertPredicate ? Hexagon::LDriuh_indexed_shl_cPt_V4 : + Hexagon::LDriuh_indexed_shl_cNotPt_V4; + case Hexagon::LDriuh_ae_indexed_shl_V4: + return !invertPredicate ? Hexagon::LDriuh_indexed_shl_cPt_V4 : + Hexagon::LDriuh_indexed_shl_cNotPt_V4; + case Hexagon::LDriw_indexed_V4: + return !invertPredicate ? Hexagon::LDriw_indexed_cPt_V4 : + Hexagon::LDriw_indexed_cNotPt_V4; + case Hexagon::LDriw_indexed_shl_V4: + return !invertPredicate ? Hexagon::LDriw_indexed_shl_cPt_V4 : + Hexagon::LDriw_indexed_shl_cNotPt_V4; + // Byte. + case Hexagon::POST_STbri: + return !invertPredicate ? Hexagon::POST_STbri_cPt : + Hexagon::POST_STbri_cNotPt; + case Hexagon::STrib: + return !invertPredicate ? Hexagon::STrib_cPt : + Hexagon::STrib_cNotPt; + case Hexagon::STrib_indexed: + return !invertPredicate ? Hexagon::STrib_indexed_cPt : + Hexagon::STrib_indexed_cNotPt; + case Hexagon::STrib_imm_V4: + return !invertPredicate ? Hexagon::STrib_imm_cPt_V4 : + Hexagon::STrib_imm_cNotPt_V4; + case Hexagon::STrib_indexed_shl_V4: + return !invertPredicate ? Hexagon::STrib_indexed_shl_cPt_V4 : + Hexagon::STrib_indexed_shl_cNotPt_V4; + // Halfword. + case Hexagon::POST_SThri: + return !invertPredicate ? Hexagon::POST_SThri_cPt : + Hexagon::POST_SThri_cNotPt; + case Hexagon::STrih: + return !invertPredicate ? Hexagon::STrih_cPt : + Hexagon::STrih_cNotPt; + case Hexagon::STrih_indexed: + return !invertPredicate ? Hexagon::STrih_indexed_cPt : + Hexagon::STrih_indexed_cNotPt; + case Hexagon::STrih_imm_V4: + return !invertPredicate ? Hexagon::STrih_imm_cPt_V4 : + Hexagon::STrih_imm_cNotPt_V4; + case Hexagon::STrih_indexed_shl_V4: + return !invertPredicate ? Hexagon::STrih_indexed_shl_cPt_V4 : + Hexagon::STrih_indexed_shl_cNotPt_V4; + // Word. + case Hexagon::POST_STwri: + return !invertPredicate ? Hexagon::POST_STwri_cPt : + Hexagon::POST_STwri_cNotPt; + case Hexagon::STriw: + return !invertPredicate ? Hexagon::STriw_cPt : + Hexagon::STriw_cNotPt; + case Hexagon::STriw_indexed: + return !invertPredicate ? Hexagon::STriw_indexed_cPt : + Hexagon::STriw_indexed_cNotPt; + case Hexagon::STriw_indexed_shl_V4: + return !invertPredicate ? Hexagon::STriw_indexed_shl_cPt_V4 : + Hexagon::STriw_indexed_shl_cNotPt_V4; + case Hexagon::STriw_imm_V4: + return !invertPredicate ? Hexagon::STriw_imm_cPt_V4 : + Hexagon::STriw_imm_cNotPt_V4; + // Double word. + case Hexagon::POST_STdri: + return !invertPredicate ? Hexagon::POST_STdri_cPt : + Hexagon::POST_STdri_cNotPt; + case Hexagon::STrid: + return !invertPredicate ? Hexagon::STrid_cPt : + Hexagon::STrid_cNotPt; + case Hexagon::STrid_indexed: + return !invertPredicate ? Hexagon::STrid_indexed_cPt : + Hexagon::STrid_indexed_cNotPt; + case Hexagon::STrid_indexed_shl_V4: + return !invertPredicate ? Hexagon::STrid_indexed_shl_cPt_V4 : + Hexagon::STrid_indexed_shl_cNotPt_V4; + // Load. + case Hexagon::LDrid: + return !invertPredicate ? Hexagon::LDrid_cPt : + Hexagon::LDrid_cNotPt; + case Hexagon::LDriw: + return !invertPredicate ? Hexagon::LDriw_cPt : + Hexagon::LDriw_cNotPt; + case Hexagon::LDrih: + return !invertPredicate ? Hexagon::LDrih_cPt : + Hexagon::LDrih_cNotPt; + case Hexagon::LDriuh: + return !invertPredicate ? Hexagon::LDriuh_cPt : + Hexagon::LDriuh_cNotPt; + case Hexagon::LDrib: + return !invertPredicate ? Hexagon::LDrib_cPt : + Hexagon::LDrib_cNotPt; + case Hexagon::LDriub: + return !invertPredicate ? Hexagon::LDriub_cPt : + Hexagon::LDriub_cNotPt; + case Hexagon::LDriubit: + return !invertPredicate ? Hexagon::LDriub_cPt : + Hexagon::LDriub_cNotPt; + // Load Indexed. + case Hexagon::LDrid_indexed: + return !invertPredicate ? Hexagon::LDrid_indexed_cPt : + Hexagon::LDrid_indexed_cNotPt; + case Hexagon::LDriw_indexed: + return !invertPredicate ? Hexagon::LDriw_indexed_cPt : + Hexagon::LDriw_indexed_cNotPt; + case Hexagon::LDrih_indexed: + return !invertPredicate ? Hexagon::LDrih_indexed_cPt : + Hexagon::LDrih_indexed_cNotPt; + case Hexagon::LDriuh_indexed: + return !invertPredicate ? Hexagon::LDriuh_indexed_cPt : + Hexagon::LDriuh_indexed_cNotPt; + case Hexagon::LDrib_indexed: + return !invertPredicate ? Hexagon::LDrib_indexed_cPt : + Hexagon::LDrib_indexed_cNotPt; + case Hexagon::LDriub_indexed: + return !invertPredicate ? Hexagon::LDriub_indexed_cPt : + Hexagon::LDriub_indexed_cNotPt; + // Post Increment Load. + case Hexagon::POST_LDrid: + return !invertPredicate ? Hexagon::POST_LDrid_cPt : + Hexagon::POST_LDrid_cNotPt; + case Hexagon::POST_LDriw: + return !invertPredicate ? Hexagon::POST_LDriw_cPt : + Hexagon::POST_LDriw_cNotPt; + case Hexagon::POST_LDrih: + return !invertPredicate ? Hexagon::POST_LDrih_cPt : + Hexagon::POST_LDrih_cNotPt; + case Hexagon::POST_LDriuh: + return !invertPredicate ? Hexagon::POST_LDriuh_cPt : + Hexagon::POST_LDriuh_cNotPt; + case Hexagon::POST_LDrib: + return !invertPredicate ? Hexagon::POST_LDrib_cPt : + Hexagon::POST_LDrib_cNotPt; + case Hexagon::POST_LDriub: + return !invertPredicate ? Hexagon::POST_LDriub_cPt : + Hexagon::POST_LDriub_cNotPt; + // DEALLOC_RETURN. + case Hexagon::DEALLOC_RET_V4: + return !invertPredicate ? Hexagon::DEALLOC_RET_cPt_V4 : + Hexagon::DEALLOC_RET_cNotPt_V4; + default: + assert(false && "Unexpected predicable instruction"); + } +} + + +bool HexagonInstrInfo:: +PredicateInstruction(MachineInstr *MI, + const SmallVectorImpl<MachineOperand> &Cond) const { + int Opc = MI->getOpcode(); + assert (isPredicable(MI) && "Expected predicable instruction"); + bool invertJump = (!Cond.empty() && Cond[0].isImm() && + (Cond[0].getImm() == 0)); + MI->setDesc(get(getMatchingCondBranchOpcode(Opc, invertJump))); + // + // This assumes that the predicate is always the first operand + // in the set of inputs. + // + MI->addOperand(MI->getOperand(MI->getNumOperands()-1)); + int oper; + for (oper = MI->getNumOperands() - 3; oper >= 0; --oper) { + MachineOperand MO = MI->getOperand(oper); + if ((MO.isReg() && !MO.isUse() && !MO.isImplicit())) { + break; + } + + if (MO.isReg()) { + MI->getOperand(oper+1).ChangeToRegister(MO.getReg(), MO.isDef(), + MO.isImplicit(), MO.isKill(), + MO.isDead(), MO.isUndef(), + MO.isDebug()); + } else if (MO.isImm()) { + MI->getOperand(oper+1).ChangeToImmediate(MO.getImm()); + } else { + assert(false && "Unexpected operand type"); + } + } + + int regPos = invertJump ? 1 : 0; + MachineOperand PredMO = Cond[regPos]; + MI->getOperand(oper+1).ChangeToRegister(PredMO.getReg(), PredMO.isDef(), + PredMO.isImplicit(), PredMO.isKill(), + PredMO.isDead(), PredMO.isUndef(), + PredMO.isDebug()); + + return true; +} + + +bool +HexagonInstrInfo:: +isProfitableToIfCvt(MachineBasicBlock &MBB, + unsigned NumCyles, + unsigned ExtraPredCycles, + const BranchProbability &Probability) const { + return true; +} + + +bool +HexagonInstrInfo:: +isProfitableToIfCvt(MachineBasicBlock &TMBB, + unsigned NumTCycles, + unsigned ExtraTCycles, + MachineBasicBlock &FMBB, + unsigned NumFCycles, + unsigned ExtraFCycles, + const BranchProbability &Probability) const { + return true; +} + + +bool HexagonInstrInfo::isPredicated(const MachineInstr *MI) const { + switch (MI->getOpcode()) { + case Hexagon::TFR_cPt: + case Hexagon::TFR_cNotPt: + case Hexagon::TFRI_cPt: + case Hexagon::TFRI_cNotPt: + case Hexagon::TFR_cdnPt: + case Hexagon::TFR_cdnNotPt: + case Hexagon::TFRI_cdnPt: + case Hexagon::TFRI_cdnNotPt: + return true; + + case Hexagon::JMP_Pred: + case Hexagon::JMP_PredNot: + case Hexagon::BRCOND: + case Hexagon::JMP_PredPt: + case Hexagon::JMP_PredNotPt: + case Hexagon::JMP_PredPnt: + case Hexagon::JMP_PredNotPnt: + return true; + + case Hexagon::LDrid_indexed_cPt_V4 : + case Hexagon::LDrid_indexed_cdnPt_V4 : + case Hexagon::LDrid_indexed_cNotPt_V4 : + case Hexagon::LDrid_indexed_cdnNotPt_V4 : + case Hexagon::LDrid_indexed_shl_cPt_V4 : + case Hexagon::LDrid_indexed_shl_cdnPt_V4 : + case Hexagon::LDrid_indexed_shl_cNotPt_V4 : + case Hexagon::LDrid_indexed_shl_cdnNotPt_V4 : + case Hexagon::LDrib_indexed_cPt_V4 : + case Hexagon::LDrib_indexed_cdnPt_V4 : + case Hexagon::LDrib_indexed_cNotPt_V4 : + case Hexagon::LDrib_indexed_cdnNotPt_V4 : + case Hexagon::LDrib_indexed_shl_cPt_V4 : + case Hexagon::LDrib_indexed_shl_cdnPt_V4 : + case Hexagon::LDrib_indexed_shl_cNotPt_V4 : + case Hexagon::LDrib_indexed_shl_cdnNotPt_V4 : + case Hexagon::LDriub_indexed_cPt_V4 : + case Hexagon::LDriub_indexed_cdnPt_V4 : + case Hexagon::LDriub_indexed_cNotPt_V4 : + case Hexagon::LDriub_indexed_cdnNotPt_V4 : + case Hexagon::LDriub_indexed_shl_cPt_V4 : + case Hexagon::LDriub_indexed_shl_cdnPt_V4 : + case Hexagon::LDriub_indexed_shl_cNotPt_V4 : + case Hexagon::LDriub_indexed_shl_cdnNotPt_V4 : + case Hexagon::LDrih_indexed_cPt_V4 : + case Hexagon::LDrih_indexed_cdnPt_V4 : + case Hexagon::LDrih_indexed_cNotPt_V4 : + case Hexagon::LDrih_indexed_cdnNotPt_V4 : + case Hexagon::LDrih_indexed_shl_cPt_V4 : + case Hexagon::LDrih_indexed_shl_cdnPt_V4 : + case Hexagon::LDrih_indexed_shl_cNotPt_V4 : + case Hexagon::LDrih_indexed_shl_cdnNotPt_V4 : + case Hexagon::LDriuh_indexed_cPt_V4 : + case Hexagon::LDriuh_indexed_cdnPt_V4 : + case Hexagon::LDriuh_indexed_cNotPt_V4 : + case Hexagon::LDriuh_indexed_cdnNotPt_V4 : + case Hexagon::LDriuh_indexed_shl_cPt_V4 : + case Hexagon::LDriuh_indexed_shl_cdnPt_V4 : + case Hexagon::LDriuh_indexed_shl_cNotPt_V4 : + case Hexagon::LDriuh_indexed_shl_cdnNotPt_V4 : + case Hexagon::LDriw_indexed_cPt_V4 : + case Hexagon::LDriw_indexed_cdnPt_V4 : + case Hexagon::LDriw_indexed_cNotPt_V4 : + case Hexagon::LDriw_indexed_cdnNotPt_V4 : + case Hexagon::LDriw_indexed_shl_cPt_V4 : + case Hexagon::LDriw_indexed_shl_cdnPt_V4 : + case Hexagon::LDriw_indexed_shl_cNotPt_V4 : + case Hexagon::LDriw_indexed_shl_cdnNotPt_V4 : + return true; + + case Hexagon::LDrid_cPt : + case Hexagon::LDrid_cNotPt : + case Hexagon::LDrid_indexed_cPt : + case Hexagon::LDrid_indexed_cNotPt : + case Hexagon::POST_LDrid_cPt : + case Hexagon::POST_LDrid_cNotPt : + case Hexagon::LDriw_cPt : + case Hexagon::LDriw_cNotPt : + case Hexagon::LDriw_indexed_cPt : + case Hexagon::LDriw_indexed_cNotPt : + case Hexagon::POST_LDriw_cPt : + case Hexagon::POST_LDriw_cNotPt : + case Hexagon::LDrih_cPt : + case Hexagon::LDrih_cNotPt : + case Hexagon::LDrih_indexed_cPt : + case Hexagon::LDrih_indexed_cNotPt : + case Hexagon::POST_LDrih_cPt : + case Hexagon::POST_LDrih_cNotPt : + case Hexagon::LDrib_cPt : + case Hexagon::LDrib_cNotPt : + case Hexagon::LDrib_indexed_cPt : + case Hexagon::LDrib_indexed_cNotPt : + case Hexagon::POST_LDrib_cPt : + case Hexagon::POST_LDrib_cNotPt : + case Hexagon::LDriuh_cPt : + case Hexagon::LDriuh_cNotPt : + case Hexagon::LDriuh_indexed_cPt : + case Hexagon::LDriuh_indexed_cNotPt : + case Hexagon::POST_LDriuh_cPt : + case Hexagon::POST_LDriuh_cNotPt : + case Hexagon::LDriub_cPt : + case Hexagon::LDriub_cNotPt : + case Hexagon::LDriub_indexed_cPt : + case Hexagon::LDriub_indexed_cNotPt : + case Hexagon::POST_LDriub_cPt : + case Hexagon::POST_LDriub_cNotPt : + return true; + + case Hexagon::LDrid_cdnPt : + case Hexagon::LDrid_cdnNotPt : + case Hexagon::LDrid_indexed_cdnPt : + case Hexagon::LDrid_indexed_cdnNotPt : + case Hexagon::POST_LDrid_cdnPt_V4 : + case Hexagon::POST_LDrid_cdnNotPt_V4 : + case Hexagon::LDriw_cdnPt : + case Hexagon::LDriw_cdnNotPt : + case Hexagon::LDriw_indexed_cdnPt : + case Hexagon::LDriw_indexed_cdnNotPt : + case Hexagon::POST_LDriw_cdnPt_V4 : + case Hexagon::POST_LDriw_cdnNotPt_V4 : + case Hexagon::LDrih_cdnPt : + case Hexagon::LDrih_cdnNotPt : + case Hexagon::LDrih_indexed_cdnPt : + case Hexagon::LDrih_indexed_cdnNotPt : + case Hexagon::POST_LDrih_cdnPt_V4 : + case Hexagon::POST_LDrih_cdnNotPt_V4 : + case Hexagon::LDrib_cdnPt : + case Hexagon::LDrib_cdnNotPt : + case Hexagon::LDrib_indexed_cdnPt : + case Hexagon::LDrib_indexed_cdnNotPt : + case Hexagon::POST_LDrib_cdnPt_V4 : + case Hexagon::POST_LDrib_cdnNotPt_V4 : + case Hexagon::LDriuh_cdnPt : + case Hexagon::LDriuh_cdnNotPt : + case Hexagon::LDriuh_indexed_cdnPt : + case Hexagon::LDriuh_indexed_cdnNotPt : + case Hexagon::POST_LDriuh_cdnPt_V4 : + case Hexagon::POST_LDriuh_cdnNotPt_V4 : + case Hexagon::LDriub_cdnPt : + case Hexagon::LDriub_cdnNotPt : + case Hexagon::LDriub_indexed_cdnPt : + case Hexagon::LDriub_indexed_cdnNotPt : + case Hexagon::POST_LDriub_cdnPt_V4 : + case Hexagon::POST_LDriub_cdnNotPt_V4 : + return true; + + case Hexagon::ADD_ri_cPt: + case Hexagon::ADD_ri_cNotPt: + case Hexagon::ADD_ri_cdnPt: + case Hexagon::ADD_ri_cdnNotPt: + case Hexagon::ADD_rr_cPt: + case Hexagon::ADD_rr_cNotPt: + case Hexagon::ADD_rr_cdnPt: + case Hexagon::ADD_rr_cdnNotPt: + case Hexagon::XOR_rr_cPt: + case Hexagon::XOR_rr_cNotPt: + case Hexagon::XOR_rr_cdnPt: + case Hexagon::XOR_rr_cdnNotPt: + case Hexagon::AND_rr_cPt: + case Hexagon::AND_rr_cNotPt: + case Hexagon::AND_rr_cdnPt: + case Hexagon::AND_rr_cdnNotPt: + case Hexagon::OR_rr_cPt: + case Hexagon::OR_rr_cNotPt: + case Hexagon::OR_rr_cdnPt: + case Hexagon::OR_rr_cdnNotPt: + case Hexagon::SUB_rr_cPt: + case Hexagon::SUB_rr_cNotPt: + case Hexagon::SUB_rr_cdnPt: + case Hexagon::SUB_rr_cdnNotPt: + case Hexagon::COMBINE_rr_cPt: + case Hexagon::COMBINE_rr_cNotPt: + case Hexagon::COMBINE_rr_cdnPt: + case Hexagon::COMBINE_rr_cdnNotPt: + return true; + + case Hexagon::ASLH_cPt_V4: + case Hexagon::ASLH_cNotPt_V4: + case Hexagon::ASRH_cPt_V4: + case Hexagon::ASRH_cNotPt_V4: + case Hexagon::SXTB_cPt_V4: + case Hexagon::SXTB_cNotPt_V4: + case Hexagon::SXTH_cPt_V4: + case Hexagon::SXTH_cNotPt_V4: + case Hexagon::ZXTB_cPt_V4: + case Hexagon::ZXTB_cNotPt_V4: + case Hexagon::ZXTH_cPt_V4: + case Hexagon::ZXTH_cNotPt_V4: + return true; + + case Hexagon::ASLH_cdnPt_V4: + case Hexagon::ASLH_cdnNotPt_V4: + case Hexagon::ASRH_cdnPt_V4: + case Hexagon::ASRH_cdnNotPt_V4: + case Hexagon::SXTB_cdnPt_V4: + case Hexagon::SXTB_cdnNotPt_V4: + case Hexagon::SXTH_cdnPt_V4: + case Hexagon::SXTH_cdnNotPt_V4: + case Hexagon::ZXTB_cdnPt_V4: + case Hexagon::ZXTB_cdnNotPt_V4: + case Hexagon::ZXTH_cdnPt_V4: + case Hexagon::ZXTH_cdnNotPt_V4: + return true; + + default: + return false; + } +} + + +bool +HexagonInstrInfo::DefinesPredicate(MachineInstr *MI, + std::vector<MachineOperand> &Pred) const { + for (unsigned oper = 0; oper < MI->getNumOperands(); ++oper) { + MachineOperand MO = MI->getOperand(oper); + if (MO.isReg() && MO.isDef()) { + const TargetRegisterClass* RC = RI.getMinimalPhysRegClass(MO.getReg()); + if (RC == Hexagon::PredRegsRegisterClass) { + Pred.push_back(MO); + return true; + } + } + } + return false; +} + + +bool +HexagonInstrInfo:: +SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1, + const SmallVectorImpl<MachineOperand> &Pred2) const { + // TODO: Fix this + return false; +} + + +// +// We indicate that we want to reverse the branch by +// inserting a 0 at the beginning of the Cond vector. +// +bool HexagonInstrInfo:: +ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const { + if (!Cond.empty() && Cond[0].isImm() && Cond[0].getImm() == 0) { + Cond.erase(Cond.begin()); + } else { + Cond.insert(Cond.begin(), MachineOperand::CreateImm(0)); + } + return false; +} + + +bool HexagonInstrInfo:: +isProfitableToDupForIfCvt(MachineBasicBlock &MBB,unsigned NumInstrs, + const BranchProbability &Probability) const { + return (NumInstrs <= 4); +} + +bool HexagonInstrInfo::isDeallocRet(const MachineInstr *MI) const { + switch (MI->getOpcode()) { + case Hexagon::DEALLOC_RET_V4 : + case Hexagon::DEALLOC_RET_cPt_V4 : + case Hexagon::DEALLOC_RET_cNotPt_V4 : + case Hexagon::DEALLOC_RET_cdnPnt_V4 : + case Hexagon::DEALLOC_RET_cNotdnPnt_V4 : + case Hexagon::DEALLOC_RET_cdnPt_V4 : + case Hexagon::DEALLOC_RET_cNotdnPt_V4 : + return true; + } + return false; +} + + +bool HexagonInstrInfo:: +isValidOffset(const int Opcode, const int Offset) const { + // This function is to check whether the "Offset" is in the correct range of + // the given "Opcode". If "Offset" is not in the correct range, "ADD_ri" is + // inserted to calculate the final address. Due to this reason, the function + // assumes that the "Offset" has correct alignment. + + switch(Opcode) { + + case Hexagon::LDriw: + case Hexagon::STriw: + case Hexagon::STriwt: + assert((Offset % 4 == 0) && "Offset has incorrect alignment"); + return (Offset >= Hexagon_MEMW_OFFSET_MIN) && + (Offset <= Hexagon_MEMW_OFFSET_MAX); + + case Hexagon::LDrid: + case Hexagon::STrid: + assert((Offset % 8 == 0) && "Offset has incorrect alignment"); + return (Offset >= Hexagon_MEMD_OFFSET_MIN) && + (Offset <= Hexagon_MEMD_OFFSET_MAX); + + case Hexagon::LDrih: + case Hexagon::LDriuh: + case Hexagon::STrih: + case Hexagon::LDrih_ae: + assert((Offset % 2 == 0) && "Offset has incorrect alignment"); + return (Offset >= Hexagon_MEMH_OFFSET_MIN) && + (Offset <= Hexagon_MEMH_OFFSET_MAX); + + case Hexagon::LDrib: + case Hexagon::STrib: + case Hexagon::LDriub: + case Hexagon::LDriubit: + case Hexagon::LDrib_ae: + case Hexagon::LDriub_ae: + return (Offset >= Hexagon_MEMB_OFFSET_MIN) && + (Offset <= Hexagon_MEMB_OFFSET_MAX); + + case Hexagon::ADD_ri: + case Hexagon::TFR_FI: + return (Offset >= Hexagon_ADDI_OFFSET_MIN) && + (Offset <= Hexagon_ADDI_OFFSET_MAX); + + case Hexagon::MEMw_ADDSUBi_indexed_MEM_V4 : + case Hexagon::MEMw_ADDi_indexed_MEM_V4 : + case Hexagon::MEMw_SUBi_indexed_MEM_V4 : + case Hexagon::MEMw_ADDr_indexed_MEM_V4 : + case Hexagon::MEMw_SUBr_indexed_MEM_V4 : + case Hexagon::MEMw_ANDr_indexed_MEM_V4 : + case Hexagon::MEMw_ORr_indexed_MEM_V4 : + case Hexagon::MEMw_ADDSUBi_MEM_V4 : + case Hexagon::MEMw_ADDi_MEM_V4 : + case Hexagon::MEMw_SUBi_MEM_V4 : + case Hexagon::MEMw_ADDr_MEM_V4 : + case Hexagon::MEMw_SUBr_MEM_V4 : + case Hexagon::MEMw_ANDr_MEM_V4 : + case Hexagon::MEMw_ORr_MEM_V4 : + assert ((Offset % 4) == 0 && "MEMOPw offset is not aligned correctly." ); + return (0 <= Offset && Offset <= 255); + + case Hexagon::MEMh_ADDSUBi_indexed_MEM_V4 : + case Hexagon::MEMh_ADDi_indexed_MEM_V4 : + case Hexagon::MEMh_SUBi_indexed_MEM_V4 : + case Hexagon::MEMh_ADDr_indexed_MEM_V4 : + case Hexagon::MEMh_SUBr_indexed_MEM_V4 : + case Hexagon::MEMh_ANDr_indexed_MEM_V4 : + case Hexagon::MEMh_ORr_indexed_MEM_V4 : + case Hexagon::MEMh_ADDSUBi_MEM_V4 : + case Hexagon::MEMh_ADDi_MEM_V4 : + case Hexagon::MEMh_SUBi_MEM_V4 : + case Hexagon::MEMh_ADDr_MEM_V4 : + case Hexagon::MEMh_SUBr_MEM_V4 : + case Hexagon::MEMh_ANDr_MEM_V4 : + case Hexagon::MEMh_ORr_MEM_V4 : + assert ((Offset % 2) == 0 && "MEMOPh offset is not aligned correctly." ); + return (0 <= Offset && Offset <= 127); + + case Hexagon::MEMb_ADDSUBi_indexed_MEM_V4 : + case Hexagon::MEMb_ADDi_indexed_MEM_V4 : + case Hexagon::MEMb_SUBi_indexed_MEM_V4 : + case Hexagon::MEMb_ADDr_indexed_MEM_V4 : + case Hexagon::MEMb_SUBr_indexed_MEM_V4 : + case Hexagon::MEMb_ANDr_indexed_MEM_V4 : + case Hexagon::MEMb_ORr_indexed_MEM_V4 : + case Hexagon::MEMb_ADDSUBi_MEM_V4 : + case Hexagon::MEMb_ADDi_MEM_V4 : + case Hexagon::MEMb_SUBi_MEM_V4 : + case Hexagon::MEMb_ADDr_MEM_V4 : + case Hexagon::MEMb_SUBr_MEM_V4 : + case Hexagon::MEMb_ANDr_MEM_V4 : + case Hexagon::MEMb_ORr_MEM_V4 : + return (0 <= Offset && Offset <= 63); + + // LDri_pred and STriw_pred are pseudo operations, so it has to take offset of + // any size. Later pass knows how to handle it. + case Hexagon::STriw_pred: + case Hexagon::LDriw_pred: + return true; + + // INLINEASM is very special. + case Hexagon::INLINEASM: + return true; + } + + assert(0 && "No offset range is defined for this opcode. Please define it in \ + the above switch statement!"); +} + + +// +// Check if the Offset is a valid auto-inc imm by Load/Store Type. +// +bool HexagonInstrInfo:: +isValidAutoIncImm(const EVT VT, const int Offset) const { + + if (VT == MVT::i64) { + return (Offset >= Hexagon_MEMD_AUTOINC_MIN && + Offset <= Hexagon_MEMD_AUTOINC_MAX && + (Offset & 0x7) == 0); + } + if (VT == MVT::i32) { + return (Offset >= Hexagon_MEMW_AUTOINC_MIN && + Offset <= Hexagon_MEMW_AUTOINC_MAX && + (Offset & 0x3) == 0); + } + if (VT == MVT::i16) { + return (Offset >= Hexagon_MEMH_AUTOINC_MIN && + Offset <= Hexagon_MEMH_AUTOINC_MAX && + (Offset & 0x1) == 0); + } + if (VT == MVT::i8) { + return (Offset >= Hexagon_MEMB_AUTOINC_MIN && + Offset <= Hexagon_MEMB_AUTOINC_MAX); + } + + assert(0 && "Not an auto-inc opc!"); + + return false; +} + + +bool HexagonInstrInfo:: +isMemOp(const MachineInstr *MI) const { + switch (MI->getOpcode()) + { + case Hexagon::MEMw_ADDSUBi_indexed_MEM_V4 : + case Hexagon::MEMw_ADDi_indexed_MEM_V4 : + case Hexagon::MEMw_SUBi_indexed_MEM_V4 : + case Hexagon::MEMw_ADDr_indexed_MEM_V4 : + case Hexagon::MEMw_SUBr_indexed_MEM_V4 : + case Hexagon::MEMw_ANDr_indexed_MEM_V4 : + case Hexagon::MEMw_ORr_indexed_MEM_V4 : + case Hexagon::MEMw_ADDSUBi_MEM_V4 : + case Hexagon::MEMw_ADDi_MEM_V4 : + case Hexagon::MEMw_SUBi_MEM_V4 : + case Hexagon::MEMw_ADDr_MEM_V4 : + case Hexagon::MEMw_SUBr_MEM_V4 : + case Hexagon::MEMw_ANDr_MEM_V4 : + case Hexagon::MEMw_ORr_MEM_V4 : + case Hexagon::MEMh_ADDSUBi_indexed_MEM_V4 : + case Hexagon::MEMh_ADDi_indexed_MEM_V4 : + case Hexagon::MEMh_SUBi_indexed_MEM_V4 : + case Hexagon::MEMh_ADDr_indexed_MEM_V4 : + case Hexagon::MEMh_SUBr_indexed_MEM_V4 : + case Hexagon::MEMh_ANDr_indexed_MEM_V4 : + case Hexagon::MEMh_ORr_indexed_MEM_V4 : + case Hexagon::MEMh_ADDSUBi_MEM_V4 : + case Hexagon::MEMh_ADDi_MEM_V4 : + case Hexagon::MEMh_SUBi_MEM_V4 : + case Hexagon::MEMh_ADDr_MEM_V4 : + case Hexagon::MEMh_SUBr_MEM_V4 : + case Hexagon::MEMh_ANDr_MEM_V4 : + case Hexagon::MEMh_ORr_MEM_V4 : + case Hexagon::MEMb_ADDSUBi_indexed_MEM_V4 : + case Hexagon::MEMb_ADDi_indexed_MEM_V4 : + case Hexagon::MEMb_SUBi_indexed_MEM_V4 : + case Hexagon::MEMb_ADDr_indexed_MEM_V4 : + case Hexagon::MEMb_SUBr_indexed_MEM_V4 : + case Hexagon::MEMb_ANDr_indexed_MEM_V4 : + case Hexagon::MEMb_ORr_indexed_MEM_V4 : + case Hexagon::MEMb_ADDSUBi_MEM_V4 : + case Hexagon::MEMb_ADDi_MEM_V4 : + case Hexagon::MEMb_SUBi_MEM_V4 : + case Hexagon::MEMb_ADDr_MEM_V4 : + case Hexagon::MEMb_SUBr_MEM_V4 : + case Hexagon::MEMb_ANDr_MEM_V4 : + case Hexagon::MEMb_ORr_MEM_V4 : + return true; + } + return false; +} + + +bool HexagonInstrInfo:: +isSpillPredRegOp(const MachineInstr *MI) const { + switch (MI->getOpcode()) + { + case Hexagon::STriw_pred : + case Hexagon::LDriw_pred : + return true; + } + return false; +} + + +bool HexagonInstrInfo::isConditionalALU32 (const MachineInstr* MI) const { + const HexagonRegisterInfo& QRI = getRegisterInfo(); + switch (MI->getOpcode()) + { + case Hexagon::ADD_ri_cPt: + case Hexagon::ADD_ri_cNotPt: + case Hexagon::ADD_rr_cPt: + case Hexagon::ADD_rr_cNotPt: + case Hexagon::XOR_rr_cPt: + case Hexagon::XOR_rr_cNotPt: + case Hexagon::AND_rr_cPt: + case Hexagon::AND_rr_cNotPt: + case Hexagon::OR_rr_cPt: + case Hexagon::OR_rr_cNotPt: + case Hexagon::SUB_rr_cPt: + case Hexagon::SUB_rr_cNotPt: + case Hexagon::COMBINE_rr_cPt: + case Hexagon::COMBINE_rr_cNotPt: + return true; + case Hexagon::ASLH_cPt_V4: + case Hexagon::ASLH_cNotPt_V4: + case Hexagon::ASRH_cPt_V4: + case Hexagon::ASRH_cNotPt_V4: + case Hexagon::SXTB_cPt_V4: + case Hexagon::SXTB_cNotPt_V4: + case Hexagon::SXTH_cPt_V4: + case Hexagon::SXTH_cNotPt_V4: + case Hexagon::ZXTB_cPt_V4: + case Hexagon::ZXTB_cNotPt_V4: + case Hexagon::ZXTH_cPt_V4: + case Hexagon::ZXTH_cNotPt_V4: + return QRI.Subtarget.getHexagonArchVersion() == HexagonSubtarget::V4; + + default: + return false; + } + return false; +} + + +bool HexagonInstrInfo:: +isConditionalLoad (const MachineInstr* MI) const { + const HexagonRegisterInfo& QRI = getRegisterInfo(); + switch (MI->getOpcode()) + { + case Hexagon::LDrid_cPt : + case Hexagon::LDrid_cNotPt : + case Hexagon::LDrid_indexed_cPt : + case Hexagon::LDrid_indexed_cNotPt : + case Hexagon::LDriw_cPt : + case Hexagon::LDriw_cNotPt : + case Hexagon::LDriw_indexed_cPt : + case Hexagon::LDriw_indexed_cNotPt : + case Hexagon::LDrih_cPt : + case Hexagon::LDrih_cNotPt : + case Hexagon::LDrih_indexed_cPt : + case Hexagon::LDrih_indexed_cNotPt : + case Hexagon::LDrib_cPt : + case Hexagon::LDrib_cNotPt : + case Hexagon::LDrib_indexed_cPt : + case Hexagon::LDrib_indexed_cNotPt : + case Hexagon::LDriuh_cPt : + case Hexagon::LDriuh_cNotPt : + case Hexagon::LDriuh_indexed_cPt : + case Hexagon::LDriuh_indexed_cNotPt : + case Hexagon::LDriub_cPt : + case Hexagon::LDriub_cNotPt : + case Hexagon::LDriub_indexed_cPt : + case Hexagon::LDriub_indexed_cNotPt : + return true; + case Hexagon::POST_LDrid_cPt : + case Hexagon::POST_LDrid_cNotPt : + case Hexagon::POST_LDriw_cPt : + case Hexagon::POST_LDriw_cNotPt : + case Hexagon::POST_LDrih_cPt : + case Hexagon::POST_LDrih_cNotPt : + case Hexagon::POST_LDrib_cPt : + case Hexagon::POST_LDrib_cNotPt : + case Hexagon::POST_LDriuh_cPt : + case Hexagon::POST_LDriuh_cNotPt : + case Hexagon::POST_LDriub_cPt : + case Hexagon::POST_LDriub_cNotPt : + return QRI.Subtarget.getHexagonArchVersion() == HexagonSubtarget::V4; + case Hexagon::LDrid_indexed_cPt_V4 : + case Hexagon::LDrid_indexed_cNotPt_V4 : + case Hexagon::LDrid_indexed_shl_cPt_V4 : + case Hexagon::LDrid_indexed_shl_cNotPt_V4 : + case Hexagon::LDrib_indexed_cPt_V4 : + case Hexagon::LDrib_indexed_cNotPt_V4 : + case Hexagon::LDrib_indexed_shl_cPt_V4 : + case Hexagon::LDrib_indexed_shl_cNotPt_V4 : + case Hexagon::LDriub_indexed_cPt_V4 : + case Hexagon::LDriub_indexed_cNotPt_V4 : + case Hexagon::LDriub_indexed_shl_cPt_V4 : + case Hexagon::LDriub_indexed_shl_cNotPt_V4 : + case Hexagon::LDrih_indexed_cPt_V4 : + case Hexagon::LDrih_indexed_cNotPt_V4 : + case Hexagon::LDrih_indexed_shl_cPt_V4 : + case Hexagon::LDrih_indexed_shl_cNotPt_V4 : + case Hexagon::LDriuh_indexed_cPt_V4 : + case Hexagon::LDriuh_indexed_cNotPt_V4 : + case Hexagon::LDriuh_indexed_shl_cPt_V4 : + case Hexagon::LDriuh_indexed_shl_cNotPt_V4 : + case Hexagon::LDriw_indexed_cPt_V4 : + case Hexagon::LDriw_indexed_cNotPt_V4 : + case Hexagon::LDriw_indexed_shl_cPt_V4 : + case Hexagon::LDriw_indexed_shl_cNotPt_V4 : + return QRI.Subtarget.getHexagonArchVersion() == HexagonSubtarget::V4; + default: + return false; + } + return false; +} diff --git a/lib/Target/Hexagon/HexagonInstrInfo.h b/lib/Target/Hexagon/HexagonInstrInfo.h new file mode 100644 index 0000000000..d549c4694b --- /dev/null +++ b/lib/Target/Hexagon/HexagonInstrInfo.h @@ -0,0 +1,166 @@ +//=- HexagonInstrInfo.h - Hexagon Instruction Information ---------*- 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 the Hexagon implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef HexagonINSTRUCTIONINFO_H +#define HexagonINSTRUCTIONINFO_H + +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetFrameLowering.h" +#include "HexagonRegisterInfo.h" + + +#define GET_INSTRINFO_HEADER +#include "HexagonGenInstrInfo.inc" + +namespace llvm { + +class HexagonInstrInfo : public HexagonGenInstrInfo { + const HexagonRegisterInfo RI; + const HexagonSubtarget& Subtarget; +public: + explicit HexagonInstrInfo(HexagonSubtarget &ST); + + /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As + /// such, whenever a client has an instance of instruction info, it should + /// always be able to get register info as well (through this method). + /// + virtual const HexagonRegisterInfo &getRegisterInfo() const { return RI; } + + /// isLoadFromStackSlot - If the specified machine instruction is a direct + /// load from a stack slot, return the virtual or physical register number of + /// the destination along with the FrameIndex of the loaded stack slot. If + /// not, return 0. This predicate must return 0 if the instruction has + /// any side effects other than loading from the stack slot. + virtual unsigned isLoadFromStackSlot(const MachineInstr *MI, + int &FrameIndex) const; + + /// isStoreToStackSlot - If the specified machine instruction is a direct + /// store to a stack slot, return the virtual or physical register number of + /// the source reg along with the FrameIndex of the loaded stack slot. If + /// not, return 0. This predicate must return 0 if the instruction has + /// any side effects other than storing to the stack slot. + virtual unsigned isStoreToStackSlot(const MachineInstr *MI, + int &FrameIndex) const; + + + virtual bool AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl<MachineOperand> &Cond, + bool AllowModify) const; + + virtual unsigned RemoveBranch(MachineBasicBlock &MBB) const; + + virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const SmallVectorImpl<MachineOperand> &Cond, + DebugLoc DL) const; + + virtual void copyPhysReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, DebugLoc DL, + unsigned DestReg, unsigned SrcReg, + bool KillSrc) const; + + virtual void storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned SrcReg, bool isKill, int FrameIndex, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const; + + virtual void storeRegToAddr(MachineFunction &MF, unsigned SrcReg, bool isKill, + SmallVectorImpl<MachineOperand> &Addr, + const TargetRegisterClass *RC, + SmallVectorImpl<MachineInstr*> &NewMIs) const; + + virtual void loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned DestReg, int FrameIndex, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const; + + virtual void loadRegFromAddr(MachineFunction &MF, unsigned DestReg, + SmallVectorImpl<MachineOperand> &Addr, + const TargetRegisterClass *RC, + SmallVectorImpl<MachineInstr*> &NewMIs) const; + + virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF, + MachineInstr* MI, + const SmallVectorImpl<unsigned> &Ops, + int FrameIndex) const; + + virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF, + MachineInstr* MI, + const SmallVectorImpl<unsigned> &Ops, + MachineInstr* LoadMI) const { + return 0; + } + + unsigned createVR(MachineFunction* MF, MVT VT) const; + + virtual bool isPredicable(MachineInstr *MI) const; + virtual bool + PredicateInstruction(MachineInstr *MI, + const SmallVectorImpl<MachineOperand> &Cond) const; + + virtual bool isProfitableToIfCvt(MachineBasicBlock &MBB, unsigned NumCyles, + unsigned ExtraPredCycles, + const BranchProbability &Probability) const; + + virtual bool isProfitableToIfCvt(MachineBasicBlock &TMBB, + unsigned NumTCycles, unsigned ExtraTCycles, + MachineBasicBlock &FMBB, + unsigned NumFCycles, unsigned ExtraFCycles, + const BranchProbability &Probability) const; + + virtual bool isPredicated(const MachineInstr *MI) const; + virtual bool DefinesPredicate(MachineInstr *MI, + std::vector<MachineOperand> &Pred) const; + virtual bool + SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1, + const SmallVectorImpl<MachineOperand> &Pred2) const; + + virtual bool + ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const; + + virtual bool + isProfitableToDupForIfCvt(MachineBasicBlock &MBB,unsigned NumCycles, + const BranchProbability &Probability) const; + + bool isValidOffset(const int Opcode, const int Offset) const; + bool isValidAutoIncImm(const EVT VT, const int Offset) const; + bool isMemOp(const MachineInstr *MI) const; + bool isSpillPredRegOp(const MachineInstr *MI) const; + bool isU6_3Immediate(const int value) const; + bool isU6_2Immediate(const int value) const; + bool isU6_1Immediate(const int value) const; + bool isU6_0Immediate(const int value) const; + bool isS4_3Immediate(const int value) const; + bool isS4_2Immediate(const int value) const; + bool isS4_1Immediate(const int value) const; + bool isS4_0Immediate(const int value) const; + bool isS12_Immediate(const int value) const; + bool isU6_Immediate(const int value) const; + bool isS8_Immediate(const int value) const; + bool isS6_Immediate(const int value) const; + + bool isConditionalALU32 (const MachineInstr* MI) const; + bool isConditionalLoad (const MachineInstr* MI) const; + bool isDeallocRet(const MachineInstr *MI) const; + +private: + int getMatchingCondBranchOpcode(int Opc, bool sense) const; + +}; + +} + +#endif diff --git a/lib/Target/Hexagon/HexagonInstrInfo.td b/lib/Target/Hexagon/HexagonInstrInfo.td new file mode 100644 index 0000000000..cc508b772a --- /dev/null +++ b/lib/Target/Hexagon/HexagonInstrInfo.td @@ -0,0 +1,3014 @@ +//==- HexagonInstrInfo.td - Target Description for Hexagon -*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the Hexagon instructions in TableGen format. +// +//===----------------------------------------------------------------------===// + +include "HexagonInstrFormats.td" +include "HexagonImmediates.td" + +//===----------------------------------------------------------------------===// +// Hexagon Instruction Predicate Definitions. +//===----------------------------------------------------------------------===// +def HasV2T : Predicate<"Subtarget.hasV2TOps()">; +def HasV2TOnly : Predicate<"Subtarget.hasV2TOpsOnly()">; +def NoV2T : Predicate<"!Subtarget.hasV2TOps()">; +def HasV3T : Predicate<"Subtarget.hasV3TOps()">; +def HasV3TOnly : Predicate<"Subtarget.hasV3TOpsOnly()">; +def NoV3T : Predicate<"!Subtarget.hasV3TOps()">; +def HasV4T : Predicate<"Subtarget.hasV4TOps()">; +def NoV4T : Predicate<"!Subtarget.hasV4TOps()">; +def UseMEMOP : Predicate<"Subtarget.useMemOps()">; + +// Addressing modes. +def ADDRrr : ComplexPattern<i32, 2, "SelectADDRrr", [], []>; +def ADDRri : ComplexPattern<i32, 2, "SelectADDRri", [frameindex], []>; +def ADDRriS11_0 : ComplexPattern<i32, 2, "SelectADDRriS11_0", [frameindex], []>; +def ADDRriS11_1 : ComplexPattern<i32, 2, "SelectADDRriS11_1", [frameindex], []>; +def ADDRriS11_2 : ComplexPattern<i32, 2, "SelectADDRriS11_2", [frameindex], []>; +def ADDRriS11_3 : ComplexPattern<i32, 2, "SelectADDRriS11_3", [frameindex], []>; +def ADDRriU6_0 : ComplexPattern<i32, 2, "SelectADDRriU6_0", [frameindex], []>; +def ADDRriU6_1 : ComplexPattern<i32, 2, "SelectADDRriU6_1", [frameindex], []>; +def ADDRriU6_2 : ComplexPattern<i32, 2, "SelectADDRriU6_2", [frameindex], []>; + +// Address operands. +def MEMrr : Operand<i32> { + let PrintMethod = "printHexagonMEMrrOperand"; + let MIOperandInfo = (ops IntRegs, IntRegs); +} + +// Address operands +def MEMri : Operand<i32> { + let PrintMethod = "printHexagonMEMriOperand"; + let MIOperandInfo = (ops IntRegs, IntRegs); +} + +def MEMri_s11_2 : Operand<i32>, + ComplexPattern<i32, 2, "SelectMEMriS11_2", []> { + let PrintMethod = "printHexagonMEMriOperand"; + let MIOperandInfo = (ops IntRegs, s11Imm); +} + +def FrameIndex : Operand<i32> { + let PrintMethod = "printHexagonFrameIndexOperand"; + let MIOperandInfo = (ops IntRegs, s11Imm); +} + +let PrintMethod = "printGlobalOperand" in + def globaladdress : Operand<i32>; + +let PrintMethod = "printJumpTable" in + def jumptablebase : Operand<i32>; + +def brtarget : Operand<OtherVT>; +def calltarget : Operand<i32>; + +def bblabel : Operand<i32>; +def bbl : SDNode<"ISD::BasicBlock", SDTPtrLeaf , [], "BasicBlockSDNode">; + +def symbolHi32 : Operand<i32> { + let PrintMethod = "printSymbolHi"; +} +def symbolLo32 : Operand<i32> { + let PrintMethod = "printSymbolLo"; +} + +// Multi-class for logical operators. +multiclass ALU32_rr_ri<string OpcStr, SDNode OpNode> { + def rr : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c), + !strconcat("$dst = ", !strconcat(OpcStr, "($b, $c)")), + [(set IntRegs:$dst, (OpNode IntRegs:$b, IntRegs:$c))]>; + def ri : ALU32_ri<(outs IntRegs:$dst), (ins s10Imm:$b, IntRegs:$c), + !strconcat("$dst = ", !strconcat(OpcStr, "(#$b, $c)")), + [(set IntRegs:$dst, (OpNode s10Imm:$b, IntRegs:$c))]>; +} + +// Multi-class for compare ops. +let isCompare = 1 in { +multiclass CMP64_rr<string OpcStr, PatFrag OpNode> { + def rr : ALU64_rr<(outs PredRegs:$dst), (ins DoubleRegs:$b, DoubleRegs:$c), + !strconcat("$dst = ", !strconcat(OpcStr, "($b, $c)")), + [(set PredRegs:$dst, (OpNode DoubleRegs:$b, DoubleRegs:$c))]>; +} +multiclass CMP32_rr<string OpcStr, PatFrag OpNode> { + def rr : ALU32_rr<(outs PredRegs:$dst), (ins IntRegs:$b, IntRegs:$c), + !strconcat("$dst = ", !strconcat(OpcStr, "($b, $c)")), + [(set PredRegs:$dst, (OpNode IntRegs:$b, IntRegs:$c))]>; +} + +multiclass CMP32_rr_ri_s10<string OpcStr, PatFrag OpNode> { + def rr : ALU32_rr<(outs PredRegs:$dst), (ins IntRegs:$b, IntRegs:$c), + !strconcat("$dst = ", !strconcat(OpcStr, "($b, $c)")), + [(set PredRegs:$dst, (OpNode IntRegs:$b, IntRegs:$c))]>; + def ri : ALU32_ri<(outs PredRegs:$dst), (ins IntRegs:$b, s10Imm:$c), + !strconcat("$dst = ", !strconcat(OpcStr, "($b, #$c)")), + [(set PredRegs:$dst, (OpNode IntRegs:$b, s10ImmPred:$c))]>; +} + +multiclass CMP32_rr_ri_u9<string OpcStr, PatFrag OpNode> { + def rr : ALU32_rr<(outs PredRegs:$dst), (ins IntRegs:$b, IntRegs:$c), + !strconcat("$dst = ", !strconcat(OpcStr, "($b, $c)")), + [(set PredRegs:$dst, (OpNode IntRegs:$b, IntRegs:$c))]>; + def ri : ALU32_ri<(outs PredRegs:$dst), (ins IntRegs:$b, u9Imm:$c), + !strconcat("$dst = ", !strconcat(OpcStr, "($b, #$c)")), + [(set PredRegs:$dst, (OpNode IntRegs:$b, u9ImmPred:$c))]>; +} + +multiclass CMP32_ri_u9<string OpcStr, PatFrag OpNode> { + def ri : ALU32_ri<(outs PredRegs:$dst), (ins IntRegs:$b, u9Imm:$c), + !strconcat("$dst = ", !strconcat(OpcStr, "($b, #$c)")), + [(set PredRegs:$dst, (OpNode IntRegs:$b, u9ImmPred:$c))]>; +} + +multiclass CMP32_ri_s8<string OpcStr, PatFrag OpNode> { + def ri : ALU32_ri<(outs PredRegs:$dst), (ins IntRegs:$b, s8Imm:$c), + !strconcat("$dst = ", !strconcat(OpcStr, "($b, #$c)")), + [(set PredRegs:$dst, (OpNode IntRegs:$b, s8ImmPred:$c))]>; +} +} + +//===----------------------------------------------------------------------===// +// Instructions +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// http://qualnet.qualcomm.com/~erich/v1/htmldocs/index.html +// http://qualnet.qualcomm.com/~erich/v2/htmldocs/index.html +// http://qualnet.qualcomm.com/~erich/v3/htmldocs/index.html +// http://qualnet.qualcomm.com/~erich/v4/htmldocs/index.html +// http://qualnet.qualcomm.com/~erich/v5/htmldocs/index.html +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// ALU32/ALU + +//===----------------------------------------------------------------------===// +// Add. +let isPredicable = 1 in +def ADD_rr : ALU32_rr<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2), + "$dst = add($src1, $src2)", + [(set IntRegs:$dst, (add IntRegs:$src1, IntRegs:$src2))]>; + +let isPredicable = 1 in +def ADD_ri : ALU32_ri<(outs IntRegs:$dst), + (ins IntRegs:$src1, s16Imm:$src2), + "$dst = add($src1, #$src2)", + [(set IntRegs:$dst, (add IntRegs:$src1, s16ImmPred:$src2))]>; + +// Logical operations. +let isPredicable = 1 in +def XOR_rr : ALU32_rr<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2), + "$dst = xor($src1, $src2)", + [(set IntRegs:$dst, (xor IntRegs:$src1, IntRegs:$src2))]>; + +let isPredicable = 1 in +def AND_rr : ALU32_rr<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2), + "$dst = and($src1, $src2)", + [(set IntRegs:$dst, (and IntRegs:$src1, IntRegs:$src2))]>; + +def OR_ri : ALU32_ri<(outs IntRegs:$dst), + (ins IntRegs:$src1, s8Imm:$src2), + "$dst = or($src1, #$src2)", + [(set IntRegs:$dst, (or IntRegs:$src1, s8ImmPred:$src2))]>; + +def NOT_rr : ALU32_rr<(outs IntRegs:$dst), + (ins IntRegs:$src1), + "$dst = not($src1)", + [(set IntRegs:$dst, (not IntRegs:$src1))]>; + +def AND_ri : ALU32_ri<(outs IntRegs:$dst), + (ins IntRegs:$src1, s10Imm:$src2), + "$dst = and($src1, #$src2)", + [(set IntRegs:$dst, (and IntRegs:$src1, s10ImmPred:$src2))]>; + +let isPredicable = 1 in +def OR_rr : ALU32_rr<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2), + "$dst = or($src1, $src2)", + [(set IntRegs:$dst, (or IntRegs:$src1, IntRegs:$src2))]>; + +// Negate. +def NEG : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1), + "$dst = neg($src1)", + [(set IntRegs:$dst, (ineg IntRegs:$src1))]>; +// Nop. +let neverHasSideEffects = 1 in +def NOP : ALU32_rr<(outs), (ins), + "nop", + []>; + +// Subtract. +let isPredicable = 1 in +def SUB_rr : ALU32_rr<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2), + "$dst = sub($src1, $src2)", + [(set IntRegs:$dst, (sub IntRegs:$src1, IntRegs:$src2))]>; + +// Transfer immediate. +let isReMaterializable = 1, isPredicable = 1 in +def TFRI : ALU32_ri<(outs IntRegs:$dst), (ins s16Imm:$src1), + "$dst = #$src1", + [(set IntRegs:$dst, s16ImmPred:$src1)]>; + +// Transfer register. +let neverHasSideEffects = 1, isPredicable = 1 in +def TFR : ALU32_ri<(outs IntRegs:$dst), (ins IntRegs:$src1), + "$dst = $src1", + []>; + +// Transfer control register. +let neverHasSideEffects = 1 in +def TFCR : CRInst<(outs CRRegs:$dst), (ins IntRegs:$src1), + "$dst = $src1", + []>; +//===----------------------------------------------------------------------===// +// ALU32/ALU - +//===----------------------------------------------------------------------===// + + +//===----------------------------------------------------------------------===// +// ALU32/PERM + +//===----------------------------------------------------------------------===// + +// Combine. +let isPredicable = 1, neverHasSideEffects = 1 in +def COMBINE_rr : ALU32_rr<(outs DoubleRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2), + "$dst = combine($src1, $src2)", + []>; + +// Mux. +def VMUX_prr64 : ALU64_rr<(outs DoubleRegs:$dst), (ins PredRegs:$src1, + DoubleRegs:$src2, + DoubleRegs:$src3), + "$dst = vmux($src1, $src2, $src3)", + []>; + +def MUX_rr : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, + IntRegs:$src2, IntRegs:$src3), + "$dst = mux($src1, $src2, $src3)", + [(set IntRegs:$dst, (select PredRegs:$src1, IntRegs:$src2, + IntRegs:$src3))]>; + +def MUX_ir : ALU32_ir<(outs IntRegs:$dst), (ins PredRegs:$src1, s8Imm:$src2, + IntRegs:$src3), + "$dst = mux($src1, #$src2, $src3)", + [(set IntRegs:$dst, (select PredRegs:$src1, + s8ImmPred:$src2, IntRegs:$src3))]>; + +def MUX_ri : ALU32_ri<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2, + s8Imm:$src3), + "$dst = mux($src1, $src2, #$src3)", + [(set IntRegs:$dst, (select PredRegs:$src1, IntRegs:$src2, + s8ImmPred:$src3))]>; + +def MUX_ii : ALU32_ii<(outs IntRegs:$dst), (ins PredRegs:$src1, s8Imm:$src2, + s8Imm:$src3), + "$dst = mux($src1, #$src2, #$src3)", + [(set IntRegs:$dst, (select PredRegs:$src1, s8ImmPred:$src2, + s8ImmPred:$src3))]>; + +// Shift halfword. +let isPredicable = 1 in +def ASLH : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1), + "$dst = aslh($src1)", + [(set IntRegs:$dst, (shl 16, IntRegs:$src1))]>; + +let isPredicable = 1 in +def ASRH : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1), + "$dst = asrh($src1)", + [(set IntRegs:$dst, (sra 16, IntRegs:$src1))]>; + +// Sign extend. +let isPredicable = 1 in +def SXTB : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1), + "$dst = sxtb($src1)", + [(set IntRegs:$dst, (sext_inreg IntRegs:$src1, i8))]>; + +let isPredicable = 1 in +def SXTH : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1), + "$dst = sxth($src1)", + [(set IntRegs:$dst, (sext_inreg IntRegs:$src1, i16))]>; + +// Zero extend. +let isPredicable = 1, neverHasSideEffects = 1 in +def ZXTB : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1), + "$dst = zxtb($src1)", + []>; + +let isPredicable = 1, neverHasSideEffects = 1 in +def ZXTH : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1), + "$dst = zxth($src1)", + []>; +//===----------------------------------------------------------------------===// +// ALU32/PERM - +//===----------------------------------------------------------------------===// + + +//===----------------------------------------------------------------------===// +// ALU32/PRED + +//===----------------------------------------------------------------------===// + +// Conditional add. +let neverHasSideEffects = 1 in +def ADD_ri_cPt : ALU32_ri<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, s16Imm:$src3), + "if ($src1) $dst = add($src2, #$src3)", + []>; + +let neverHasSideEffects = 1 in +def ADD_ri_cNotPt : ALU32_ri<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, s16Imm:$src3), + "if (!$src1) $dst = add($src2, #$src3)", + []>; + +let neverHasSideEffects = 1 in +def ADD_ri_cdnPt : ALU32_ri<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, s16Imm:$src3), + "if ($src1.new) $dst = add($src2, #$src3)", + []>; + +let neverHasSideEffects = 1 in +def ADD_ri_cdnNotPt : ALU32_ri<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, s16Imm:$src3), + "if (!$src1.new) $dst = add($src2, #$src3)", + []>; + +let neverHasSideEffects = 1 in +def ADD_rr_cPt : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if ($src1) $dst = add($src2, $src3)", + []>; + +let neverHasSideEffects = 1 in +def ADD_rr_cNotPt : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if (!$src1) $dst = add($src2, $src3)", + []>; + +let neverHasSideEffects = 1 in +def ADD_rr_cdnPt : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if ($src1.new) $dst = add($src2, $src3)", + []>; + +let neverHasSideEffects = 1 in +def ADD_rr_cdnNotPt : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if (!$src1.new) $dst = add($src2, $src3)", + []>; + + +// Conditional combine. + +let neverHasSideEffects = 1 in +def COMBINE_rr_cPt : ALU32_rr<(outs DoubleRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if ($src1) $dst = combine($src2, $src3)", + []>; + +let neverHasSideEffects = 1 in +def COMBINE_rr_cNotPt : ALU32_rr<(outs DoubleRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if (!$src1) $dst = combine($src2, $src3)", + []>; + +let neverHasSideEffects = 1 in +def COMBINE_rr_cdnPt : ALU32_rr<(outs DoubleRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if ($src1.new) $dst = combine($src2, $src3)", + []>; + +let neverHasSideEffects = 1 in +def COMBINE_rr_cdnNotPt : ALU32_rr<(outs DoubleRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if (!$src1.new) $dst = combine($src2, $src3)", + []>; + +// Conditional logical operations. + +def XOR_rr_cPt : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if ($src1) $dst = xor($src2, $src3)", + []>; + +def XOR_rr_cNotPt : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if (!$src1) $dst = xor($src2, $src3)", + []>; + +def XOR_rr_cdnPt : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if ($src1.new) $dst = xor($src2, $src3)", + []>; + +def XOR_rr_cdnNotPt : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if (!$src1.new) $dst = xor($src2, $src3)", + []>; + +def AND_rr_cPt : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if ($src1) $dst = and($src2, $src3)", + []>; + +def AND_rr_cNotPt : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if (!$src1) $dst = and($src2, $src3)", + []>; + +def AND_rr_cdnPt : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if ($src1.new) $dst = and($src2, $src3)", + []>; + +def AND_rr_cdnNotPt : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if (!$src1.new) $dst = and($src2, $src3)", + []>; + +def OR_rr_cPt : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if ($src1) $dst = or($src2, $src3)", + []>; + +def OR_rr_cNotPt : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if (!$src1) $dst = or($src2, $src3)", + []>; + +def OR_rr_cdnPt : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if ($src1.new) $dst = or($src2, $src3)", + []>; + +def OR_rr_cdnNotPt : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if (!$src1.new) $dst = or($src2, $src3)", + []>; + + +// Conditional subtract. + +def SUB_rr_cPt : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if ($src1) $dst = sub($src2, $src3)", + []>; + +def SUB_rr_cNotPt : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if (!$src1) $dst = sub($src2, $src3)", + []>; + +def SUB_rr_cdnPt : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if ($src1.new) $dst = sub($src2, $src3)", + []>; + +def SUB_rr_cdnNotPt : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if (!$src1.new) $dst = sub($src2, $src3)", + []>; + + +// Conditional transfer. + +let neverHasSideEffects = 1 in +def TFR_cPt : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, IntRegs:$src2), + "if ($src1) $dst = $src2", + []>; + +let neverHasSideEffects = 1 in +def TFR_cNotPt : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, + IntRegs:$src2), + "if (!$src1) $dst = $src2", + []>; + +let neverHasSideEffects = 1 in +def TFRI_cPt : ALU32_ri<(outs IntRegs:$dst), (ins PredRegs:$src1, s12Imm:$src2), + "if ($src1) $dst = #$src2", + []>; + +let neverHasSideEffects = 1 in +def TFRI_cNotPt : ALU32_ri<(outs IntRegs:$dst), (ins PredRegs:$src1, + s12Imm:$src2), + "if (!$src1) $dst = #$src2", + []>; + +let neverHasSideEffects = 1 in +def TFR_cdnPt : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, + IntRegs:$src2), + "if ($src1.new) $dst = $src2", + []>; + +let neverHasSideEffects = 1 in +def TFR_cdnNotPt : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, + IntRegs:$src2), + "if (!$src1.new) $dst = $src2", + []>; + +let neverHasSideEffects = 1 in +def TFRI_cdnPt : ALU32_ri<(outs IntRegs:$dst), (ins PredRegs:$src1, + s12Imm:$src2), + "if ($src1.new) $dst = #$src2", + []>; + +let neverHasSideEffects = 1 in +def TFRI_cdnNotPt : ALU32_ri<(outs IntRegs:$dst), (ins PredRegs:$src1, + s12Imm:$src2), + "if (!$src1.new) $dst = #$src2", + []>; + +// Compare. +defm CMPGTU : CMP32_rr_ri_u9<"cmp.gtu", setugt>; +defm CMPGT : CMP32_rr_ri_s10<"cmp.gt", setgt>; +defm CMPLT : CMP32_rr<"cmp.lt", setlt>; +defm CMPEQ : CMP32_rr_ri_s10<"cmp.eq", seteq>; +defm CMPGE : CMP32_ri_s8<"cmp.ge", setge>; +defm CMPGEU : CMP32_ri_u9<"cmp.geu", setuge>; +//===----------------------------------------------------------------------===// +// ALU32/PRED - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// ALU32/VH + +//===----------------------------------------------------------------------===// +// Vector add halfwords + +// Vector averagehalfwords + +// Vector subtract halfwords +//===----------------------------------------------------------------------===// +// ALU32/VH - +//===----------------------------------------------------------------------===// + + +//===----------------------------------------------------------------------===// +// ALU64/ALU + +//===----------------------------------------------------------------------===// +// Add. +def ADD64_rr : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, + DoubleRegs:$src2), + "$dst = add($src1, $src2)", + [(set DoubleRegs:$dst, (add DoubleRegs:$src1, + DoubleRegs:$src2))]>; + +// Add halfword. + +// Compare. +defm CMPEHexagon4 : CMP64_rr<"cmp.eq", seteq>; +defm CMPGT64 : CMP64_rr<"cmp.gt", setgt>; +defm CMPGTU64 : CMP64_rr<"cmp.gtu", setugt>; + +// Logical operations. +def AND_rr64 : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, + DoubleRegs:$src2), + "$dst = and($src1, $src2)", + [(set DoubleRegs:$dst, (and DoubleRegs:$src1, + DoubleRegs:$src2))]>; + +def OR_rr64 : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, + DoubleRegs:$src2), + "$dst = or($src1, $src2)", + [(set DoubleRegs:$dst, (or DoubleRegs:$src1, DoubleRegs:$src2))]>; + +def XOR_rr64 : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, + DoubleRegs:$src2), + "$dst = xor($src1, $src2)", + [(set DoubleRegs:$dst, (xor DoubleRegs:$src1, + DoubleRegs:$src2))]>; + +// Maximum. +def MAXw_rr : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + "$dst = max($src2, $src1)", + [(set IntRegs:$dst, (select (i1 (setlt IntRegs:$src2, + IntRegs:$src1)), + IntRegs:$src1, IntRegs:$src2))]>; + +// Minimum. +def MINw_rr : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + "$dst = min($src2, $src1)", + [(set IntRegs:$dst, (select (i1 (setgt IntRegs:$src2, + IntRegs:$src1)), + IntRegs:$src1, IntRegs:$src2))]>; + +// Subtract. +def SUB64_rr : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, + DoubleRegs:$src2), + "$dst = sub($src1, $src2)", + [(set DoubleRegs:$dst, (sub DoubleRegs:$src1, + DoubleRegs:$src2))]>; + +// Subtract halfword. + +// Transfer register. +let neverHasSideEffects = 1 in +def TFR_64 : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1), + "$dst = $src1", + []>; +//===----------------------------------------------------------------------===// +// ALU64/ALU - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// ALU64/BIT + +//===----------------------------------------------------------------------===// +// +//===----------------------------------------------------------------------===// +// ALU64/BIT - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// ALU64/PERM + +//===----------------------------------------------------------------------===// +// +//===----------------------------------------------------------------------===// +// ALU64/PERM - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// ALU64/VB + +//===----------------------------------------------------------------------===// +// +//===----------------------------------------------------------------------===// +// ALU64/VB - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// ALU64/VH + +//===----------------------------------------------------------------------===// +// +//===----------------------------------------------------------------------===// +// ALU64/VH - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// ALU64/VW + +//===----------------------------------------------------------------------===// +// +//===----------------------------------------------------------------------===// +// ALU64/VW - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// CR + +//===----------------------------------------------------------------------===// +// Logical reductions on predicates. + +// Looping instructions. + +// Pipelined looping instructions. + +// Logical operations on predicates. +def AND_pp : SInst<(outs PredRegs:$dst), (ins PredRegs:$src1, PredRegs:$src2), + "$dst = and($src1, $src2)", + [(set PredRegs:$dst, (and PredRegs:$src1, PredRegs:$src2))]>; + +let neverHasSideEffects = 1 in +def AND_pnotp : SInst<(outs PredRegs:$dst), (ins PredRegs:$src1, + PredRegs:$src2), + "$dst = and($src1, !$src2)", + []>; + +def NOT_pp : SInst<(outs PredRegs:$dst), (ins PredRegs:$src1), + "$dst = not($src1)", + [(set PredRegs:$dst, (not PredRegs:$src1))]>; + +def ANY_pp : SInst<(outs PredRegs:$dst), (ins PredRegs:$src1), + "$dst = any8($src1)", + []>; + +def ALL_pp : SInst<(outs PredRegs:$dst), (ins PredRegs:$src1), + "$dst = all8($src1)", + []>; + +def VITPACK_pp : SInst<(outs IntRegs:$dst), (ins PredRegs:$src1, + PredRegs:$src2), + "$dst = vitpack($src1, $src2)", + []>; + +def VALIGN_rrp : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, + DoubleRegs:$src2, + PredRegs:$src3), + "$dst = valignb($src1, $src2, $src3)", + []>; + +def VSPLICE_rrp : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, + DoubleRegs:$src2, + PredRegs:$src3), + "$dst = vspliceb($src1, $src2, $src3)", + []>; + +def MASK_p : SInst<(outs DoubleRegs:$dst), (ins PredRegs:$src1), + "$dst = mask($src1)", + []>; + +def NOT_Ps : SInst<(outs PredRegs:$dst), (ins PredRegs:$src1), + "$dst = not($src1)", + [(set PredRegs:$dst, (not PredRegs:$src1))]>; + +def OR_pp : SInst<(outs PredRegs:$dst), (ins PredRegs:$src1, PredRegs:$src2), + "$dst = or($src1, $src2)", + [(set PredRegs:$dst, (or PredRegs:$src1, PredRegs:$src2))]>; + +def XOR_pp : SInst<(outs PredRegs:$dst), (ins PredRegs:$src1, PredRegs:$src2), + "$dst = xor($src1, $src2)", + [(set PredRegs:$dst, (xor PredRegs:$src1, PredRegs:$src2))]>; + + +// User control register transfer. +//===----------------------------------------------------------------------===// +// CR - +//===----------------------------------------------------------------------===// + + +//===----------------------------------------------------------------------===// +// J + +//===----------------------------------------------------------------------===// +// Jump to address. +let isBranch = 1, isTerminator=1, isBarrier = 1, isPredicable = 1 in { + def JMP : JInst< (outs), + (ins brtarget:$offset), + "jump $offset", + [(br bb:$offset)]>; +} + +// if (p0) jump +let isBranch = 1, isTerminator=1, Defs = [PC] in { + def JMP_Pred : JInst< (outs), + (ins PredRegs:$src, brtarget:$offset), + "if ($src) jump $offset", + [(brcond PredRegs:$src, bb:$offset)]>; +} + +// if (!p0) jump +let isBranch = 1, isTerminator=1, neverHasSideEffects = 1, Defs = [PC] in { + def JMP_PredNot : JInst< (outs), + (ins PredRegs:$src, brtarget:$offset), + "if (!$src) jump $offset", + []>; +} + +let isTerminator = 1, isBranch = 1, neverHasSideEffects = 1, Defs = [PC] in { + def BRCOND : JInst < (outs), (ins PredRegs:$pred, brtarget:$dst), + "if ($pred) jump $dst", + []>; +} + +// Jump to address conditioned on new predicate. +// if (p0) jump:t +let isBranch = 1, isTerminator=1, neverHasSideEffects = 1, Defs = [PC] in { + def JMP_PredPt : JInst< (outs), + (ins PredRegs:$src, brtarget:$offset), + "if ($src.new) jump:t $offset", + []>; +} + +// if (!p0) jump:t +let isBranch = 1, isTerminator=1, neverHasSideEffects = 1, Defs = [PC] in { + def JMP_PredNotPt : JInst< (outs), + (ins PredRegs:$src, brtarget:$offset), + "if (!$src.new) jump:t $offset", + []>; +} + +// Not taken. +let isBranch = 1, isTerminator=1, neverHasSideEffects = 1, Defs = [PC] in { + def JMP_PredPnt : JInst< (outs), + (ins PredRegs:$src, brtarget:$offset), + "if ($src.new) jump:nt $offset", + []>; +} + +// Not taken. +let isBranch = 1, isTerminator=1, neverHasSideEffects = 1, Defs = [PC] in { + def JMP_PredNotPnt : JInst< (outs), + (ins PredRegs:$src, brtarget:$offset), + "if (!$src.new) jump:nt $offset", + []>; +} +//===----------------------------------------------------------------------===// +// J - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// JR + +//===----------------------------------------------------------------------===// +def retflag : SDNode<"HexagonISD::RET_FLAG", SDTNone, + [SDNPHasChain, SDNPOptInGlue]>; + +// Jump to address from register. +let isReturn = 1, isTerminator = 1, isBarrier = 1, + Defs = [PC], Uses = [R31] in { + def JMPR: JRInst<(outs), (ins), + "jumpr r31", + [(retflag)]>; +} + +// Jump to address from register. +let isReturn = 1, isTerminator = 1, isBarrier = 1, + Defs = [PC], Uses = [R31] in { + def JMPR_cPt: JRInst<(outs), (ins PredRegs:$src1), + "if ($src1) jumpr r31", + []>; +} + +// Jump to address from register. +let isReturn = 1, isTerminator = 1, isBarrier = 1, + Defs = [PC], Uses = [R31] in { + def JMPR_cNotPt: JRInst<(outs), (ins PredRegs:$src1), + "if (!$src1) jumpr r31", + []>; +} + +//===----------------------------------------------------------------------===// +// JR - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// LD + +//===----------------------------------------------------------------------===// +/// +/// Make sure that in post increment load, the first operand is always the post +/// increment operand. +/// +// Load doubleword. +let isPredicable = 1 in +def LDrid : LDInst<(outs DoubleRegs:$dst), + (ins MEMri:$addr), + "$dst = memd($addr)", + [(set DoubleRegs:$dst, (load ADDRriS11_3:$addr))]>; + +let isPredicable = 1, AddedComplexity = 20 in +def LDrid_indexed : LDInst<(outs DoubleRegs:$dst), + (ins IntRegs:$src1, s11_3Imm:$offset), + "$dst=memd($src1+#$offset)", + [(set DoubleRegs:$dst, (load (add IntRegs:$src1, + s11_3ImmPred:$offset)))]>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDrid_GP : LDInst<(outs DoubleRegs:$dst), + (ins globaladdress:$global, u16Imm:$offset), + "$dst=memd(#$global+$offset)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDd_GP : LDInst<(outs DoubleRegs:$dst), + (ins globaladdress:$global), + "$dst=memd(#$global)", + []>; + +let isPredicable = 1, mayLoad = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in +def POST_LDrid : LDInstPI<(outs DoubleRegs:$dst, IntRegs:$dst2), + (ins IntRegs:$src1, s4Imm:$offset), + "$dst = memd($src1++#$offset)", + [], + "$src1 = $dst2">; + +// Load doubleword conditionally. +let mayLoad = 1, neverHasSideEffects = 1 in +def LDrid_cPt : LDInst<(outs DoubleRegs:$dst), + (ins PredRegs:$src1, MEMri:$addr), + "if ($src1) $dst = memd($addr)", + []>; + + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDrid_cNotPt : LDInst<(outs DoubleRegs:$dst), + (ins PredRegs:$src1, MEMri:$addr), + "if (!$src1) $dst = memd($addr)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDrid_indexed_cPt : LDInst<(outs DoubleRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, u6_3Imm:$src3), + "if ($src1) $dst=memd($src2+#$src3)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDrid_indexed_cNotPt : LDInst<(outs DoubleRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, u6_3Imm:$src3), + "if (!$src1) $dst=memd($src2+#$src3)", + []>; + +let mayLoad = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in +def POST_LDrid_cPt : LDInstPI<(outs DoubleRegs:$dst1, IntRegs:$dst2), + (ins PredRegs:$src1, IntRegs:$src2, s4_3Imm:$src3), + "if ($src1) $dst1 = memd($src2++#$src3)", + [], + "$src2 = $dst2">; + +let mayLoad = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in +def POST_LDrid_cNotPt : LDInstPI<(outs DoubleRegs:$dst1, IntRegs:$dst2), + (ins PredRegs:$src1, IntRegs:$src2, s4_3Imm:$src3), + "if (!$src1) $dst1 = memd($src2++#$src3)", + [], + "$src2 = $dst2">; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDrid_cdnPt : LDInst<(outs DoubleRegs:$dst), + (ins PredRegs:$src1, MEMri:$addr), + "if ($src1.new) $dst = memd($addr)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDrid_cdnNotPt : LDInst<(outs DoubleRegs:$dst), + (ins PredRegs:$src1, MEMri:$addr), + "if (!$src1.new) $dst = memd($addr)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDrid_indexed_cdnPt : LDInst<(outs DoubleRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, u6_3Imm:$src3), + "if ($src1.new) $dst=memd($src2+#$src3)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDrid_indexed_cdnNotPt : LDInst<(outs DoubleRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, u6_3Imm:$src3), + "if (!$src1.new) $dst=memd($src2+#$src3)", + []>; + + +// Load byte. +let isPredicable = 1 in +def LDrib : LDInst<(outs IntRegs:$dst), + (ins MEMri:$addr), + "$dst = memb($addr)", + [(set IntRegs:$dst, (sextloadi8 ADDRriS11_0:$addr))]>; + +def LDrib_ae : LDInst<(outs IntRegs:$dst), + (ins MEMri:$addr), + "$dst = memb($addr)", + [(set IntRegs:$dst, (extloadi8 ADDRriS11_0:$addr))]>; + +// Indexed load byte. +let isPredicable = 1, AddedComplexity = 20 in +def LDrib_indexed : LDInst<(outs IntRegs:$dst), + (ins IntRegs:$src1, s11_0Imm:$offset), + "$dst=memb($src1+#$offset)", + [(set IntRegs:$dst, (sextloadi8 (add IntRegs:$src1, + s11_0ImmPred:$offset)))]>; + + +// Indexed load byte any-extend. +let AddedComplexity = 20 in +def LDrib_ae_indexed : LDInst<(outs IntRegs:$dst), + (ins IntRegs:$src1, s11_0Imm:$offset), + "$dst=memb($src1+#$offset)", + [(set IntRegs:$dst, (extloadi8 (add IntRegs:$src1, + s11_0ImmPred:$offset)))]>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDrib_GP : LDInst<(outs IntRegs:$dst), + (ins globaladdress:$global, u16Imm:$offset), + "$dst=memb(#$global+$offset)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDb_GP : LDInst<(outs IntRegs:$dst), + (ins globaladdress:$global), + "$dst=memb(#$global)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDub_GP : LDInst<(outs IntRegs:$dst), + (ins globaladdress:$global), + "$dst=memub(#$global)", + []>; + +let isPredicable = 1, mayLoad = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in +def POST_LDrib : LDInstPI<(outs IntRegs:$dst, IntRegs:$dst2), + (ins IntRegs:$src1, s4Imm:$offset), + "$dst = memb($src1++#$offset)", + [], + "$src1 = $dst2">; + +// Load byte conditionally. +let mayLoad = 1, neverHasSideEffects = 1 in +def LDrib_cPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, MEMri:$addr), + "if ($src1) $dst = memb($addr)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDrib_cNotPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, MEMri:$addr), + "if (!$src1) $dst = memb($addr)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDrib_indexed_cPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3), + "if ($src1) $dst = memb($src2+#$src3)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDrib_indexed_cNotPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3), + "if (!$src1) $dst = memb($src2+#$src3)", + []>; + +let mayLoad = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in +def POST_LDrib_cPt : LDInstPI<(outs IntRegs:$dst1, IntRegs:$dst2), + (ins PredRegs:$src1, IntRegs:$src2, s4_0Imm:$src3), + "if ($src1) $dst1 = memb($src2++#$src3)", + [], + "$src2 = $dst2">; + +let mayLoad = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in +def POST_LDrib_cNotPt : LDInstPI<(outs IntRegs:$dst1, IntRegs:$dst2), + (ins PredRegs:$src1, IntRegs:$src2, s4_0Imm:$src3), + "if (!$src1) $dst1 = memb($src2++#$src3)", + [], + "$src2 = $dst2">; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDrib_cdnPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, MEMri:$addr), + "if ($src1.new) $dst = memb($addr)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDrib_cdnNotPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, MEMri:$addr), + "if (!$src1.new) $dst = memb($addr)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDrib_indexed_cdnPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3), + "if ($src1.new) $dst = memb($src2+#$src3)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDrib_indexed_cdnNotPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3), + "if (!$src1.new) $dst = memb($src2+#$src3)", + []>; + + +// Load halfword. +let isPredicable = 1 in +def LDrih : LDInst<(outs IntRegs:$dst), + (ins MEMri:$addr), + "$dst = memh($addr)", + [(set IntRegs:$dst, (sextloadi16 ADDRriS11_1:$addr))]>; + +let isPredicable = 1, AddedComplexity = 20 in +def LDrih_indexed : LDInst<(outs IntRegs:$dst), + (ins IntRegs:$src1, s11_1Imm:$offset), + "$dst=memh($src1+#$offset)", + [(set IntRegs:$dst, (sextloadi16 (add IntRegs:$src1, + s11_1ImmPred:$offset)))] >; + +def LDrih_ae : LDInst<(outs IntRegs:$dst), + (ins MEMri:$addr), + "$dst = memh($addr)", + [(set IntRegs:$dst, (extloadi16 ADDRriS11_1:$addr))]>; + +let AddedComplexity = 20 in +def LDrih_ae_indexed : LDInst<(outs IntRegs:$dst), + (ins IntRegs:$src1, s11_1Imm:$offset), + "$dst=memh($src1+#$offset)", + [(set IntRegs:$dst, (extloadi16 (add IntRegs:$src1, + s11_1ImmPred:$offset)))] >; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDrih_GP : LDInst<(outs IntRegs:$dst), + (ins globaladdress:$global, u16Imm:$offset), + "$dst=memh(#$global+$offset)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDh_GP : LDInst<(outs IntRegs:$dst), + (ins globaladdress:$global), + "$dst=memh(#$global)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDuh_GP : LDInst<(outs IntRegs:$dst), + (ins globaladdress:$global), + "$dst=memuh(#$global)", + []>; + + +let isPredicable = 1, mayLoad = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in +def POST_LDrih : LDInstPI<(outs IntRegs:$dst, IntRegs:$dst2), + (ins IntRegs:$src1, s4Imm:$offset), + "$dst = memh($src1++#$offset)", + [], + "$src1 = $dst2">; + +// Load halfword conditionally. +let mayLoad = 1, neverHasSideEffects = 1 in +def LDrih_cPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, MEMri:$addr), + "if ($src1) $dst = memh($addr)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDrih_cNotPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, MEMri:$addr), + "if (!$src1) $dst = memh($addr)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDrih_indexed_cPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3), + "if ($src1) $dst = memh($src2+#$src3)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDrih_indexed_cNotPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3), + "if (!$src1) $dst = memh($src2+#$src3)", + []>; + +let mayLoad = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in +def POST_LDrih_cPt : LDInstPI<(outs IntRegs:$dst1, IntRegs:$dst2), + (ins PredRegs:$src1, IntRegs:$src2, s4_1Imm:$src3), + "if ($src1) $dst1 = memh($src2++#$src3)", + [], + "$src2 = $dst2">; + +let mayLoad = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in +def POST_LDrih_cNotPt : LDInstPI<(outs IntRegs:$dst1, IntRegs:$dst2), + (ins PredRegs:$src1, IntRegs:$src2, s4_1Imm:$src3), + "if (!$src1) $dst1 = memh($src2++#$src3)", + [], + "$src2 = $dst2">; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDrih_cdnPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, MEMri:$addr), + "if ($src1.new) $dst = memh($addr)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDrih_cdnNotPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, MEMri:$addr), + "if (!$src1.new) $dst = memh($addr)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDrih_indexed_cdnPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3), + "if ($src1.new) $dst = memh($src2+#$src3)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDrih_indexed_cdnNotPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3), + "if (!$src1.new) $dst = memh($src2+#$src3)", + []>; + +// Load unsigned byte. +let isPredicable = 1 in +def LDriub : LDInst<(outs IntRegs:$dst), + (ins MEMri:$addr), + "$dst = memub($addr)", + [(set IntRegs:$dst, (zextloadi8 ADDRriS11_0:$addr))]>; + +let isPredicable = 1 in +def LDriubit : LDInst<(outs IntRegs:$dst), + (ins MEMri:$addr), + "$dst = memub($addr)", + [(set IntRegs:$dst, (zextloadi1 ADDRriS11_0:$addr))]>; + +let isPredicable = 1, AddedComplexity = 20 in +def LDriub_indexed : LDInst<(outs IntRegs:$dst), + (ins IntRegs:$src1, s11_0Imm:$offset), + "$dst=memub($src1+#$offset)", + [(set IntRegs:$dst, (zextloadi8 (add IntRegs:$src1, + s11_0ImmPred:$offset)))]>; + +let AddedComplexity = 20 in +def LDriubit_indexed : LDInst<(outs IntRegs:$dst), + (ins IntRegs:$src1, s11_0Imm:$offset), + "$dst=memub($src1+#$offset)", + [(set IntRegs:$dst, (zextloadi1 (add IntRegs:$src1, + s11_0ImmPred:$offset)))]>; + +def LDriub_ae : LDInst<(outs IntRegs:$dst), + (ins MEMri:$addr), + "$dst = memub($addr)", + [(set IntRegs:$dst, (extloadi8 ADDRriS11_0:$addr))]>; + + +let AddedComplexity = 20 in +def LDriub_ae_indexed : LDInst<(outs IntRegs:$dst), + (ins IntRegs:$src1, s11_0Imm:$offset), + "$dst=memub($src1+#$offset)", + [(set IntRegs:$dst, (extloadi8 (add IntRegs:$src1, + s11_0ImmPred:$offset)))]>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDriub_GP : LDInst<(outs IntRegs:$dst), + (ins globaladdress:$global, u16Imm:$offset), + "$dst=memub(#$global+$offset)", + []>; + +let isPredicable = 1, mayLoad = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in +def POST_LDriub : LDInstPI<(outs IntRegs:$dst, IntRegs:$dst2), + (ins IntRegs:$src1, s4Imm:$offset), + "$dst = memub($src1++#$offset)", + [], + "$src1 = $dst2">; + +// Load unsigned byte conditionally. +let mayLoad = 1, neverHasSideEffects = 1 in +def LDriub_cPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, MEMri:$addr), + "if ($src1) $dst = memub($addr)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDriub_cNotPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, MEMri:$addr), + "if (!$src1) $dst = memub($addr)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDriub_indexed_cPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3), + "if ($src1) $dst = memub($src2+#$src3)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDriub_indexed_cNotPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3), + "if (!$src1) $dst = memub($src2+#$src3)", + []>; + +let mayLoad = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in +def POST_LDriub_cPt : LDInstPI<(outs IntRegs:$dst1, IntRegs:$dst2), + (ins PredRegs:$src1, IntRegs:$src2, s4_0Imm:$src3), + "if ($src1) $dst1 = memub($src2++#$src3)", + [], + "$src2 = $dst2">; + +let mayLoad = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in +def POST_LDriub_cNotPt : LDInstPI<(outs IntRegs:$dst1, IntRegs:$dst2), + (ins PredRegs:$src1, IntRegs:$src2, s4_0Imm:$src3), + "if (!$src1) $dst1 = memub($src2++#$src3)", + [], + "$src2 = $dst2">; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDriub_cdnPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, MEMri:$addr), + "if ($src1.new) $dst = memub($addr)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDriub_cdnNotPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, MEMri:$addr), + "if (!$src1.new) $dst = memub($addr)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDriub_indexed_cdnPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3), + "if ($src1.new) $dst = memub($src2+#$src3)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDriub_indexed_cdnNotPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3), + "if (!$src1.new) $dst = memub($src2+#$src3)", + []>; + +// Load unsigned halfword. +let isPredicable = 1 in +def LDriuh : LDInst<(outs IntRegs:$dst), + (ins MEMri:$addr), + "$dst = memuh($addr)", + [(set IntRegs:$dst, (zextloadi16 ADDRriS11_1:$addr))]>; + +// Indexed load unsigned halfword. +let isPredicable = 1, AddedComplexity = 20 in +def LDriuh_indexed : LDInst<(outs IntRegs:$dst), + (ins IntRegs:$src1, s11_1Imm:$offset), + "$dst=memuh($src1+#$offset)", + [(set IntRegs:$dst, (zextloadi16 (add IntRegs:$src1, + s11_1ImmPred:$offset)))]>; + +def LDriuh_ae : LDInst<(outs IntRegs:$dst), + (ins MEMri:$addr), + "$dst = memuh($addr)", + [(set IntRegs:$dst, (extloadi16 ADDRriS11_1:$addr))]>; + + +// Indexed load unsigned halfword any-extend. +let AddedComplexity = 20 in +def LDriuh_ae_indexed : LDInst<(outs IntRegs:$dst), + (ins IntRegs:$src1, s11_1Imm:$offset), + "$dst=memuh($src1+#$offset)", + [(set IntRegs:$dst, (extloadi16 (add IntRegs:$src1, + s11_1ImmPred:$offset)))] >; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDriuh_GP : LDInst<(outs IntRegs:$dst), + (ins globaladdress:$global, u16Imm:$offset), + "$dst=memuh(#$global+$offset)", + []>; + +let isPredicable = 1, mayLoad = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in +def POST_LDriuh : LDInstPI<(outs IntRegs:$dst, IntRegs:$dst2), + (ins IntRegs:$src1, s4Imm:$offset), + "$dst = memuh($src1++#$offset)", + [], + "$src1 = $dst2">; + +// Load unsigned halfword conditionally. +let mayLoad = 1, neverHasSideEffects = 1 in +def LDriuh_cPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, MEMri:$addr), + "if ($src1) $dst = memuh($addr)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDriuh_cNotPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, MEMri:$addr), + "if (!$src1) $dst = memuh($addr)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDriuh_indexed_cPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3), + "if ($src1) $dst = memuh($src2+#$src3)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDriuh_indexed_cNotPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3), + "if (!$src1) $dst = memuh($src2+#$src3)", + []>; + +let mayLoad = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in +def POST_LDriuh_cPt : LDInstPI<(outs IntRegs:$dst1, IntRegs:$dst2), + (ins PredRegs:$src1, IntRegs:$src2, s4_1Imm:$src3), + "if ($src1) $dst1 = memuh($src2++#$src3)", + [], + "$src2 = $dst2">; + +let mayLoad = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in +def POST_LDriuh_cNotPt : LDInstPI<(outs IntRegs:$dst1, IntRegs:$dst2), + (ins PredRegs:$src1, IntRegs:$src2, s4_1Imm:$src3), + "if (!$src1) $dst1 = memuh($src2++#$src3)", + [], + "$src2 = $dst2">; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDriuh_cdnPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, MEMri:$addr), + "if ($src1.new) $dst = memuh($addr)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDriuh_cdnNotPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, MEMri:$addr), + "if (!$src1.new) $dst = memuh($addr)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDriuh_indexed_cdnPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3), + "if ($src1.new) $dst = memuh($src2+#$src3)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDriuh_indexed_cdnNotPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3), + "if (!$src1.new) $dst = memuh($src2+#$src3)", + []>; + + +// Load word. +let isPredicable = 1 in +def LDriw : LDInst<(outs IntRegs:$dst), + (ins MEMri:$addr), "$dst = memw($addr)", + [(set IntRegs:$dst, (load ADDRriS11_2:$addr))]>; + +// Load predicate. +let mayLoad = 1, Defs = [R10,R11] in +def LDriw_pred : LDInst<(outs PredRegs:$dst), + (ins MEMri:$addr), + "Error; should not emit", + []>; + +// Indexed load. +let isPredicable = 1, AddedComplexity = 20 in +def LDriw_indexed : LDInst<(outs IntRegs:$dst), + (ins IntRegs:$src1, s11_2Imm:$offset), + "$dst=memw($src1+#$offset)", + [(set IntRegs:$dst, (load (add IntRegs:$src1, + s11_2ImmPred:$offset)))]>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDriw_GP : LDInst<(outs IntRegs:$dst), + (ins globaladdress:$global, u16Imm:$offset), + "$dst=memw(#$global+$offset)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDw_GP : LDInst<(outs IntRegs:$dst), + (ins globaladdress:$global), + "$dst=memw(#$global)", + []>; + +let isPredicable = 1, mayLoad = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in +def POST_LDriw : LDInstPI<(outs IntRegs:$dst, IntRegs:$dst2), + (ins IntRegs:$src1, s4Imm:$offset), + "$dst = memw($src1++#$offset)", + [], + "$src1 = $dst2">; + +// Load word conditionally. + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDriw_cPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, MEMri:$addr), + "if ($src1) $dst = memw($addr)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDriw_cNotPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, MEMri:$addr), + "if (!$src1) $dst = memw($addr)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDriw_indexed_cPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3), + "if ($src1) $dst=memw($src2+#$src3)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDriw_indexed_cNotPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3), + "if (!$src1) $dst=memw($src2+#$src3)", + []>; + +let mayLoad = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in +def POST_LDriw_cPt : LDInstPI<(outs IntRegs:$dst1, IntRegs:$dst2), + (ins PredRegs:$src1, IntRegs:$src2, s4_2Imm:$src3), + "if ($src1) $dst1 = memw($src2++#$src3)", + [], + "$src2 = $dst2">; + +let mayLoad = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in +def POST_LDriw_cNotPt : LDInstPI<(outs IntRegs:$dst1, IntRegs:$dst2), + (ins PredRegs:$src1, IntRegs:$src2, s4_2Imm:$src3), + "if (!$src1) $dst1 = memw($src2++#$src3)", + [], + "$src2 = $dst2">; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDriw_cdnPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, MEMri:$addr), + "if ($src1.new) $dst = memw($addr)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDriw_cdnNotPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, MEMri:$addr), + "if (!$src1.new) $dst = memw($addr)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDriw_indexed_cdnPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3), + "if ($src1.new) $dst=memw($src2+#$src3)", + []>; + +let mayLoad = 1, neverHasSideEffects = 1 in +def LDriw_indexed_cdnNotPt : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3), + "if (!$src1.new) $dst=memw($src2+#$src3)", + []>; + +// Deallocate stack frame. +let Defs = [R29, R30, R31], Uses = [R29], neverHasSideEffects = 1 in { + def DEALLOCFRAME : LDInst<(outs), (ins i32imm:$amt1), + "deallocframe", + []>; +} + +// Load and unpack bytes to halfwords. +//===----------------------------------------------------------------------===// +// LD - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// MTYPE/ALU + +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// +// MTYPE/ALU - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// MTYPE/COMPLEX + +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// +// MTYPE/COMPLEX - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// MTYPE/MPYH + +//===----------------------------------------------------------------------===// +// Multiply and use lower result. +// Rd=+mpyi(Rs,#u8) +def MPYI_riu : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, u8Imm:$src2), + "$dst =+ mpyi($src1, #$src2)", + [(set IntRegs:$dst, (mul IntRegs:$src1, u8ImmPred:$src2))]>; + +// Rd=-mpyi(Rs,#u8) +def MPYI_rin : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, n8Imm:$src2), + "$dst =- mpyi($src1, #$src2)", + [(set IntRegs:$dst, + (mul IntRegs:$src1, n8ImmPred:$src2))]>; + +// Rd=mpyi(Rs,#m9) +// s9 is NOT the same as m9 - but it works.. so far. +// Assembler maps to either Rd=+mpyi(Rs,#u8 or Rd=-mpyi(Rs,#u8) +// depending on the value of m9. See Arch Spec. +def MPYI_ri : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, s9Imm:$src2), + "$dst = mpyi($src1, #$src2)", + [(set IntRegs:$dst, (mul IntRegs:$src1, s9ImmPred:$src2))]>; + +// Rd=mpyi(Rs,Rt) +def MPYI : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + "$dst = mpyi($src1, $src2)", + [(set IntRegs:$dst, (mul IntRegs:$src1, IntRegs:$src2))]>; + +// Rx+=mpyi(Rs,#u8) +def MPYI_acc_ri : MInst_acc<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2, u8Imm:$src3), + "$dst += mpyi($src2, #$src3)", + [(set IntRegs:$dst, + (add (mul IntRegs:$src2, u8ImmPred:$src3), IntRegs:$src1))], + "$src1 = $dst">; + +// Rx+=mpyi(Rs,Rt) +def MPYI_acc_rr : MInst_acc<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "$dst += mpyi($src2, $src3)", + [(set IntRegs:$dst, + (add (mul IntRegs:$src2, IntRegs:$src3), IntRegs:$src1))], + "$src1 = $dst">; + +// Rx-=mpyi(Rs,#u8) +def MPYI_sub_ri : MInst_acc<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2, u8Imm:$src3), + "$dst -= mpyi($src2, #$src3)", + [(set IntRegs:$dst, + (sub IntRegs:$src1, (mul IntRegs:$src2, u8ImmPred:$src3)))], + "$src1 = $dst">; + +// Multiply and use upper result. +// Rd=mpy(Rs,Rt.H):<<1:rnd:sat +// Rd=mpy(Rs,Rt.L):<<1:rnd:sat +// Rd=mpy(Rs,Rt) +def MPY : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + "$dst = mpy($src1, $src2)", + [(set IntRegs:$dst, (mulhs IntRegs:$src1, IntRegs:$src2))]>; + +// Rd=mpy(Rs,Rt):rnd +// Rd=mpyu(Rs,Rt) +def MPYU : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + "$dst = mpyu($src1, $src2)", + [(set IntRegs:$dst, (mulhu IntRegs:$src1, IntRegs:$src2))]>; + +// Multiply and use full result. +// Rdd=mpyu(Rs,Rt) +def MPYU64 : MInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + "$dst = mpyu($src1, $src2)", + [(set DoubleRegs:$dst, (mul (i64 (anyext IntRegs:$src1)), + (i64 (anyext IntRegs:$src2))))]>; + +// Rdd=mpy(Rs,Rt) +def MPY64 : MInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + "$dst = mpy($src1, $src2)", + [(set DoubleRegs:$dst, (mul (i64 (sext IntRegs:$src1)), + (i64 (sext IntRegs:$src2))))]>; + + +// Multiply and accumulate, use full result. +// Rxx[+-]=mpy(Rs,Rt) +// Rxx+=mpy(Rs,Rt) +def MPY64_acc : MInst_acc<(outs DoubleRegs:$dst), + (ins DoubleRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "$dst += mpy($src2, $src3)", + [(set DoubleRegs:$dst, + (add (mul (i64 (sext IntRegs:$src2)), (i64 (sext IntRegs:$src3))), + DoubleRegs:$src1))], + "$src1 = $dst">; + +// Rxx-=mpy(Rs,Rt) +def MPY64_sub : MInst_acc<(outs DoubleRegs:$dst), + (ins DoubleRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "$dst -= mpy($src2, $src3)", + [(set DoubleRegs:$dst, + (sub DoubleRegs:$src1, + (mul (i64 (sext IntRegs:$src2)), (i64 (sext IntRegs:$src3)))))], + "$src1 = $dst">; + +// Rxx[+-]=mpyu(Rs,Rt) +// Rxx+=mpyu(Rs,Rt) +def MPYU64_acc : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, + IntRegs:$src2, IntRegs:$src3), + "$dst += mpyu($src2, $src3)", + [(set DoubleRegs:$dst, (add (mul (i64 (anyext IntRegs:$src2)), + (i64 (anyext IntRegs:$src3))), + DoubleRegs:$src1))],"$src1 = $dst">; + +// Rxx-=mpyu(Rs,Rt) +def MPYU64_sub : MInst_acc<(outs DoubleRegs:$dst), + (ins DoubleRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "$dst += mpyu($src2, $src3)", + [(set DoubleRegs:$dst, + (sub DoubleRegs:$src1, + (mul (i64 (anyext IntRegs:$src2)), + (i64 (anyext IntRegs:$src3)))))], + "$src1 = $dst">; + + +def ADDrr_acc : MInst_acc<(outs IntRegs: $dst), (ins IntRegs:$src1, + IntRegs:$src2, IntRegs:$src3), + "$dst += add($src2, $src3)", + [(set IntRegs:$dst, (add (add IntRegs:$src2, IntRegs:$src3), + IntRegs:$src1))], + "$src1 = $dst">; + +def ADDri_acc : MInst_acc<(outs IntRegs: $dst), (ins IntRegs:$src1, + IntRegs:$src2, s8Imm:$src3), + "$dst += add($src2, #$src3)", + [(set IntRegs:$dst, (add (add IntRegs:$src2, s8ImmPred:$src3), + IntRegs:$src1))], + "$src1 = $dst">; + +def SUBrr_acc : MInst_acc<(outs IntRegs: $dst), (ins IntRegs:$src1, + IntRegs:$src2, IntRegs:$src3), + "$dst -= add($src2, $src3)", + [(set IntRegs:$dst, (sub IntRegs:$src1, (add IntRegs:$src2, + IntRegs:$src3)))], + "$src1 = $dst">; + +def SUBri_acc : MInst_acc<(outs IntRegs: $dst), (ins IntRegs:$src1, + IntRegs:$src2, s8Imm:$src3), + "$dst -= add($src2, #$src3)", + [(set IntRegs:$dst, (sub IntRegs:$src1, + (add IntRegs:$src2, s8ImmPred:$src3)))], + "$src1 = $dst">; + +//===----------------------------------------------------------------------===// +// MTYPE/MPYH - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// MTYPE/MPYS + +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// +// MTYPE/MPYS - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// MTYPE/VB + +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// +// MTYPE/VB - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// MTYPE/VH + +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// +// MTYPE/VH - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// ST + +//===----------------------------------------------------------------------===// +/// +/// Assumptions::: ****** DO NOT IGNORE ******** +/// 1. Make sure that in post increment store, the zero'th operand is always the +/// post increment operand. +/// 2. Make sure that the store value operand(Rt/Rtt) in a store is always the +/// last operand. +/// +// Store doubleword. +let isPredicable = 1 in +def STrid : STInst<(outs), + (ins MEMri:$addr, DoubleRegs:$src1), + "memd($addr) = $src1", + [(store DoubleRegs:$src1, ADDRriS11_3:$addr)]>; + +// Indexed store double word. +let AddedComplexity = 10, isPredicable = 1 in +def STrid_indexed : STInst<(outs), + (ins IntRegs:$src1, s11_3Imm:$src2, DoubleRegs:$src3), + "memd($src1+#$src2) = $src3", + [(store DoubleRegs:$src3, + (add IntRegs:$src1, s11_3ImmPred:$src2))]>; + +let mayStore = 1, neverHasSideEffects = 1 in +def STrid_GP : STInst<(outs), + (ins globaladdress:$global, u16Imm:$offset, DoubleRegs:$src), + "memd(#$global+$offset) = $src", + []>; + +let hasCtrlDep = 1, isPredicable = 1 in +def POST_STdri : STInstPI<(outs IntRegs:$dst), + (ins DoubleRegs:$src1, IntRegs:$src2, s4Imm:$offset), + "memd($src2++#$offset) = $src1", + [(set IntRegs:$dst, + (post_store DoubleRegs:$src1, IntRegs:$src2, s4_3ImmPred:$offset))], + "$src2 = $dst">; + +// Store doubleword conditionally. +// if ([!]Pv) memd(Rs+#u6:3)=Rtt +// if (Pv) memd(Rs+#u6:3)=Rtt +let AddedComplexity = 10, mayStore = 1, neverHasSideEffects = 1 in +def STrid_cPt : STInst<(outs), + (ins PredRegs:$src1, MEMri:$addr, DoubleRegs:$src2), + "if ($src1) memd($addr) = $src2", + []>; + +// if (!Pv) memd(Rs+#u6:3)=Rtt +let AddedComplexity = 10, mayStore = 1, neverHasSideEffects = 1 in +def STrid_cNotPt : STInst<(outs), + (ins PredRegs:$src1, MEMri:$addr, DoubleRegs:$src2), + "if (!$src1) memd($addr) = $src2", + []>; + +// if (Pv) memd(Rs+#u6:3)=Rtt +let AddedComplexity = 10, mayStore = 1, neverHasSideEffects = 1 in +def STrid_indexed_cPt : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_3Imm:$src3, + DoubleRegs:$src4), + "if ($src1) memd($src2+#$src3) = $src4", + []>; + +// if (!Pv) memd(Rs+#u6:3)=Rtt +let AddedComplexity = 10, mayStore = 1, neverHasSideEffects = 1 in +def STrid_indexed_cNotPt : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_3Imm:$src3, + DoubleRegs:$src4), + "if (!$src1) memd($src2+#$src3) = $src4", + []>; + +// if ([!]Pv) memd(Rx++#s4:3)=Rtt +// if (Pv) memd(Rx++#s4:3)=Rtt +let AddedComplexity = 10, mayStore = 1, neverHasSideEffects = 1 in +def POST_STdri_cPt : STInstPI<(outs IntRegs:$dst), + (ins PredRegs:$src1, DoubleRegs:$src2, IntRegs:$src3, + s4_3Imm:$offset), + "if ($src1) memd($src3++#$offset) = $src2", + [], + "$src3 = $dst">; + +// if (!Pv) memd(Rx++#s4:3)=Rtt +let AddedComplexity = 10, mayStore = 1, neverHasSideEffects = 1 in +def POST_STdri_cNotPt : STInstPI<(outs IntRegs:$dst), + (ins PredRegs:$src1, DoubleRegs:$src2, IntRegs:$src3, + s4_3Imm:$offset), + "if (!$src1) memd($src3++#$offset) = $src2", + [], + "$src3 = $dst">; + + +// Store byte. +// memb(Rs+#s11:0)=Rt +let isPredicable = 1 in +def STrib : STInst<(outs), + (ins MEMri:$addr, IntRegs:$src1), + "memb($addr) = $src1", + [(truncstorei8 IntRegs:$src1, ADDRriS11_0:$addr)]>; + +let AddedComplexity = 10, isPredicable = 1 in +def STrib_indexed : STInst<(outs), + (ins IntRegs:$src1, s11_0Imm:$src2, IntRegs:$src3), + "memb($src1+#$src2) = $src3", + [(truncstorei8 IntRegs:$src3, (add IntRegs:$src1, + s11_0ImmPred:$src2))]>; + +// memb(gp+#u16:0)=Rt +let mayStore = 1, neverHasSideEffects = 1 in +def STrib_GP : STInst<(outs), + (ins globaladdress:$global, u16Imm:$offset, IntRegs:$src), + "memb(#$global+$offset) = $src", + []>; + +let mayStore = 1, neverHasSideEffects = 1 in +def STb_GP : STInst<(outs), + (ins globaladdress:$global, IntRegs:$src), + "memb(#$global) = $src", + []>; + +// memb(Rx++#s4:0)=Rt +let hasCtrlDep = 1, isPredicable = 1 in +def POST_STbri : STInstPI<(outs IntRegs:$dst), (ins IntRegs:$src1, + IntRegs:$src2, + s4Imm:$offset), + "memb($src2++#$offset) = $src1", + [(set IntRegs:$dst, + (post_truncsti8 IntRegs:$src1, IntRegs:$src2, + s4_0ImmPred:$offset))], + "$src2 = $dst">; + +// Store byte conditionally. +// if ([!]Pv) memb(Rs+#u6:0)=Rt +// if (Pv) memb(Rs+#u6:0)=Rt +let mayStore = 1, neverHasSideEffects = 1 in +def STrib_cPt : STInst<(outs), + (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), + "if ($src1) memb($addr) = $src2", + []>; + +// if (!Pv) memb(Rs+#u6:0)=Rt +let mayStore = 1, neverHasSideEffects = 1 in +def STrib_cNotPt : STInst<(outs), + (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), + "if (!$src1) memb($addr) = $src2", + []>; + +// if (Pv) memb(Rs+#u6:0)=Rt +let mayStore = 1, neverHasSideEffects = 1 in +def STrib_indexed_cPt : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3, IntRegs:$src4), + "if ($src1) memb($src2+#$src3) = $src4", + []>; + +// if (!Pv) memb(Rs+#u6:0)=Rt +let mayStore = 1, neverHasSideEffects = 1 in +def STrib_indexed_cNotPt : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3, IntRegs:$src4), + "if (!$src1) memb($src2+#$src3) = $src4", + []>; + +// if ([!]Pv) memb(Rx++#s4:0)=Rt +// if (Pv) memb(Rx++#s4:0)=Rt +let mayStore = 1, hasCtrlDep = 1 in +def POST_STbri_cPt : STInstPI<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_0Imm:$offset), + "if ($src1) memb($src3++#$offset) = $src2", + [],"$src3 = $dst">; + +// if (!Pv) memb(Rx++#s4:0)=Rt +let mayStore = 1, hasCtrlDep = 1 in +def POST_STbri_cNotPt : STInstPI<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_0Imm:$offset), + "if (!$src1) memb($src3++#$offset) = $src2", + [],"$src3 = $dst">; + + +// Store halfword. +// memh(Rs+#s11:1)=Rt +let isPredicable = 1 in +def STrih : STInst<(outs), + (ins MEMri:$addr, IntRegs:$src1), + "memh($addr) = $src1", + [(truncstorei16 IntRegs:$src1, ADDRriS11_1:$addr)]>; + + +let AddedComplexity = 10, isPredicable = 1 in +def STrih_indexed : STInst<(outs), + (ins IntRegs:$src1, s11_1Imm:$src2, IntRegs:$src3), + "memh($src1+#$src2) = $src3", + [(truncstorei16 IntRegs:$src3, (add IntRegs:$src1, + s11_1ImmPred:$src2))]>; + +let mayStore = 1, neverHasSideEffects = 1 in +def STrih_GP : STInst<(outs), + (ins globaladdress:$global, u16Imm:$offset, IntRegs:$src), + "memh(#$global+$offset) = $src", + []>; + +let mayStore = 1, neverHasSideEffects = 1 in +def STh_GP : STInst<(outs), + (ins globaladdress:$global, IntRegs:$src), + "memh(#$global) = $src", + []>; + +// memh(Rx++#s4:1)=Rt.H +// memh(Rx++#s4:1)=Rt +let hasCtrlDep = 1, isPredicable = 1 in +def POST_SThri : STInstPI<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2, s4Imm:$offset), + "memh($src2++#$offset) = $src1", + [(set IntRegs:$dst, + (post_truncsti16 IntRegs:$src1, IntRegs:$src2, + s4_1ImmPred:$offset))], + "$src2 = $dst">; + +// Store halfword conditionally. +// if ([!]Pv) memh(Rs+#u6:1)=Rt +// if (Pv) memh(Rs+#u6:1)=Rt +let mayStore = 1, neverHasSideEffects = 1 in +def STrih_cPt : STInst<(outs), + (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), + "if ($src1) memh($addr) = $src2", + []>; + +// if (!Pv) memh(Rs+#u6:1)=Rt +let mayStore = 1, neverHasSideEffects = 1 in +def STrih_cNotPt : STInst<(outs), + (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), + "if (!$src1) memh($addr) = $src2", + []>; + +// if (Pv) memh(Rs+#u6:1)=Rt +let mayStore = 1, neverHasSideEffects = 1 in +def STrih_indexed_cPt : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3, IntRegs:$src4), + "if ($src1) memh($src2+#$src3) = $src4", + []>; + +// if (!Pv) memh(Rs+#u6:1)=Rt +let mayStore = 1, neverHasSideEffects = 1 in +def STrih_indexed_cNotPt : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3, IntRegs:$src4), + "if (!$src1) memh($src2+#$src3) = $src4", + []>; + +// if ([!]Pv) memh(Rx++#s4:1)=Rt +// if (Pv) memh(Rx++#s4:1)=Rt +let mayStore = 1, hasCtrlDep = 1 in +def POST_SThri_cPt : STInstPI<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_1Imm:$offset), + "if ($src1) memh($src3++#$offset) = $src2", + [],"$src3 = $dst">; + +// if (!Pv) memh(Rx++#s4:1)=Rt +let mayStore = 1, hasCtrlDep = 1 in +def POST_SThri_cNotPt : STInstPI<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_1Imm:$offset), + "if (!$src1) memh($src3++#$offset) = $src2", + [],"$src3 = $dst">; + + +// Store word. +// Store predicate. +let Defs = [R10,R11] in +def STriw_pred : STInst<(outs), + (ins MEMri:$addr, PredRegs:$src1), + "Error; should not emit", + []>; + +// memw(Rs+#s11:2)=Rt +let isPredicable = 1 in +def STriw : STInst<(outs), + (ins MEMri:$addr, IntRegs:$src1), + "memw($addr) = $src1", + [(store IntRegs:$src1, ADDRriS11_2:$addr)]>; + +let AddedComplexity = 10, isPredicable = 1 in +def STriw_indexed : STInst<(outs), + (ins IntRegs:$src1, s11_2Imm:$src2, IntRegs:$src3), + "memw($src1+#$src2) = $src3", + [(store IntRegs:$src3, (add IntRegs:$src1, s11_2ImmPred:$src2))]>; + +def STriwt : STInst<(outs), + (ins MEMri:$addr, DoubleRegs:$src1), + "memw($addr) = $src1", + [(truncstorei32 DoubleRegs:$src1, ADDRriS11_2:$addr)]>; + +let mayStore = 1, neverHasSideEffects = 1 in +def STriw_GP : STInst<(outs), + (ins globaladdress:$global, u16Imm:$offset, IntRegs:$src), + "memw(#$global+$offset) = $src", + []>; + +let hasCtrlDep = 1, isPredicable = 1 in +def POST_STwri : STInstPI<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2, s4Imm:$offset), + "memw($src2++#$offset) = $src1", + [(set IntRegs:$dst, + (post_store IntRegs:$src1, IntRegs:$src2, s4_2ImmPred:$offset))], + "$src2 = $dst">; + +// Store word conditionally. +// if ([!]Pv) memw(Rs+#u6:2)=Rt +// if (Pv) memw(Rs+#u6:2)=Rt +let mayStore = 1, neverHasSideEffects = 1 in +def STriw_cPt : STInst<(outs), + (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), + "if ($src1) memw($addr) = $src2", + []>; + +// if (!Pv) memw(Rs+#u6:2)=Rt +let mayStore = 1, neverHasSideEffects = 1 in +def STriw_cNotPt : STInst<(outs), + (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), + "if (!$src1) memw($addr) = $src2", + []>; + +// if (Pv) memw(Rs+#u6:2)=Rt +let mayStore = 1, neverHasSideEffects = 1 in +def STriw_indexed_cPt : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3, IntRegs:$src4), + "if ($src1) memw($src2+#$src3) = $src4", + []>; + +// if (!Pv) memw(Rs+#u6:2)=Rt +let mayStore = 1, neverHasSideEffects = 1 in +def STriw_indexed_cNotPt : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3, IntRegs:$src4), + "if (!$src1) memw($src2+#$src3) = $src4", + []>; + +// if ([!]Pv) memw(Rx++#s4:2)=Rt +// if (Pv) memw(Rx++#s4:2)=Rt +let mayStore = 1, hasCtrlDep = 1 in +def POST_STwri_cPt : STInstPI<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_2Imm:$offset), + "if ($src1) memw($src3++#$offset) = $src2", + [],"$src3 = $dst">; + +// if (!Pv) memw(Rx++#s4:2)=Rt +let mayStore = 1, hasCtrlDep = 1 in +def POST_STwri_cNotPt : STInstPI<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_2Imm:$offset), + "if (!$src1) memw($src3++#$offset) = $src2", + [],"$src3 = $dst">; + + + +// Allocate stack frame. +let Defs = [R29, R30], Uses = [R31, R30], neverHasSideEffects = 1 in { + def ALLOCFRAME : STInst<(outs), + (ins i32imm:$amt), + "allocframe(#$amt)", + []>; +} +//===----------------------------------------------------------------------===// +// ST - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// STYPE/ALU + +//===----------------------------------------------------------------------===// +// Logical NOT. +def NOT_rr64 : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1), + "$dst = not($src1)", + [(set DoubleRegs:$dst, (not DoubleRegs:$src1))]>; + + +// Sign extend word to doubleword. +def SXTW : ALU64_rr<(outs DoubleRegs:$dst), (ins IntRegs:$src1), + "$dst = sxtw($src1)", + [(set DoubleRegs:$dst, (sext IntRegs:$src1))]>; +//===----------------------------------------------------------------------===// +// STYPE/ALU - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// STYPE/BIT + +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// +// STYPE/BIT - +//===----------------------------------------------------------------------===// + + +//===----------------------------------------------------------------------===// +// STYPE/COMPLEX + +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// +// STYPE/COMPLEX - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// STYPE/PERM + +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// +// STYPE/PERM - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// STYPE/PRED + +//===----------------------------------------------------------------------===// +// Predicate transfer. +let neverHasSideEffects = 1 in +def TFR_RsPd : SInst<(outs IntRegs:$dst), (ins PredRegs:$src1), + "$dst = $src1 // Should almost never emit this", + []>; + +def TFR_PdRs : SInst<(outs PredRegs:$dst), (ins IntRegs:$src1), + "$dst = $src1 // Should almost never emit!", + [(set PredRegs:$dst, (trunc IntRegs:$src1))]>; +//===----------------------------------------------------------------------===// +// STYPE/PRED - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// STYPE/SHIFT + +//===----------------------------------------------------------------------===// +// Shift by immediate. +def ASR_ri : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2), + "$dst = asr($src1, #$src2)", + [(set IntRegs:$dst, (sra IntRegs:$src1, u5ImmPred:$src2))]>; + +def ASRd_ri : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, u6Imm:$src2), + "$dst = asr($src1, #$src2)", + [(set DoubleRegs:$dst, (sra DoubleRegs:$src1, u6ImmPred:$src2))]>; + +def ASL : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2), + "$dst = asl($src1, #$src2)", + [(set IntRegs:$dst, (shl IntRegs:$src1, u5ImmPred:$src2))]>; + +def LSR_ri : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2), + "$dst = lsr($src1, #$src2)", + [(set IntRegs:$dst, (srl IntRegs:$src1, u5ImmPred:$src2))]>; + +def LSRd_ri : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, u6Imm:$src2), + "$dst = lsr($src1, #$src2)", + [(set DoubleRegs:$dst, (srl DoubleRegs:$src1, u6ImmPred:$src2))]>; + +def LSRd_ri_acc : SInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, + DoubleRegs:$src2, + u6Imm:$src3), + "$dst += lsr($src2, #$src3)", + [(set DoubleRegs:$dst, (add DoubleRegs:$src1, + (srl DoubleRegs:$src2, + u6ImmPred:$src3)))], + "$src1 = $dst">; + +// Shift by immediate and accumulate. +def ASR_rr_acc : SInst_acc<(outs IntRegs:$dst), (ins IntRegs:$src1, + IntRegs:$src2, + IntRegs:$src3), + "$dst += asr($src2, $src3)", + [], "$src1 = $dst">; + +// Shift by immediate and add. +def ADDASL : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2, + u3Imm:$src3), + "$dst = addasl($src1, $src2, #$src3)", + [(set IntRegs:$dst, (add IntRegs:$src1, + (shl IntRegs:$src2, + u3ImmPred:$src3)))]>; + +// Shift by register. +def ASL_rr : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + "$dst = asl($src1, $src2)", + [(set IntRegs:$dst, (shl IntRegs:$src1, IntRegs:$src2))]>; + +def ASR_rr : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + "$dst = asr($src1, $src2)", + [(set IntRegs:$dst, (sra IntRegs:$src1, IntRegs:$src2))]>; + + +def LSR_rr : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + "$dst = lsr($src1, $src2)", + [(set IntRegs:$dst, (srl IntRegs:$src1, IntRegs:$src2))]>; + +def LSLd : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, IntRegs:$src2), + "$dst = lsl($src1, $src2)", + [(set DoubleRegs:$dst, (shl DoubleRegs:$src1, IntRegs:$src2))]>; + +def ASRd_rr : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, + IntRegs:$src2), + "$dst = asr($src1, $src2)", + [(set DoubleRegs:$dst, (sra DoubleRegs:$src1, IntRegs:$src2))]>; + +def LSRd_rr : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, + IntRegs:$src2), + "$dst = lsr($src1, $src2)", + [(set DoubleRegs:$dst, (srl DoubleRegs:$src1, IntRegs:$src2))]>; + +//===----------------------------------------------------------------------===// +// STYPE/SHIFT - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// STYPE/VH + +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// +// STYPE/VH - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// STYPE/VW + +//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// +// STYPE/VW - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// SYSTEM/SUPER + +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// SYSTEM/USER + +//===----------------------------------------------------------------------===// +def SDHexagonBARRIER: SDTypeProfile<0, 0, []>; +def HexagonBARRIER: SDNode<"HexagonISD::BARRIER", SDHexagonBARRIER, + [SDNPHasChain]>; + +let hasSideEffects = 1 in +def BARRIER : STInst<(outs), (ins), + "barrier", + [(HexagonBARRIER)]>; + +//===----------------------------------------------------------------------===// +// SYSTEM/SUPER - +//===----------------------------------------------------------------------===// + +// TFRI64 - assembly mapped. +let isReMaterializable = 1 in +def TFRI64 : ALU64_rr<(outs DoubleRegs:$dst), (ins s8Imm64:$src1), + "$dst = #$src1", + [(set DoubleRegs:$dst, s8Imm64Pred:$src1)]>; + +// Pseudo instruction to encode a set of conditional transfers. +// This instruction is used instead of a mux and trades-off codesize +// for performance. We conduct this transformation optimistically in +// the hope that these instructions get promoted to dot-new transfers. +let AddedComplexity = 100 in +def TFR_condset_rr : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1, + IntRegs:$src2, + IntRegs:$src3), + "Error; should not emit", + [(set IntRegs:$dst, (select PredRegs:$src1, IntRegs:$src2, + IntRegs:$src3))]>; + +let AddedComplexity = 100 in +def TFR_condset_ii : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, s12Imm:$src2, s12Imm:$src3), + "Error; should not emit", + [(set IntRegs:$dst, (select PredRegs:$src1, + s12ImmPred:$src2, + s12ImmPred:$src3))]>; + +// Generate frameindex addresses. +let isReMaterializable = 1 in +def TFR_FI : ALU32_ri<(outs IntRegs:$dst), (ins FrameIndex:$src1), + "$dst = add($src1)", + [(set IntRegs:$dst, ADDRri:$src1)]>; + +// +// CR - Type. +// +let neverHasSideEffects = 1, Defs = [SA0, LC0] in { +def LOOP0_i : CRInst<(outs), (ins brtarget:$offset, u10Imm:$src2), + "loop0($offset, #$src2)", + []>; +} + +let neverHasSideEffects = 1, Defs = [SA0, LC0] in { +def LOOP0_r : CRInst<(outs), (ins brtarget:$offset, IntRegs:$src2), + "loop0($offset, $src2)", + []>; +} + +let isBranch = 1, isTerminator = 1, neverHasSideEffects = 1, + Defs = [PC, LC0], Uses = [SA0, LC0] in { +def ENDLOOP0 : CRInst<(outs), (ins brtarget:$offset), + ":endloop0", + []>; +} + +// Support for generating global address. +// Taken from X86InstrInfo.td. +def SDTHexagonCONST32 : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, + SDTCisPtrTy<0>]>; +def HexagonCONST32 : SDNode<"HexagonISD::CONST32", SDTHexagonCONST32>; +def HexagonCONST32_GP : SDNode<"HexagonISD::CONST32_GP", SDTHexagonCONST32>; + +// This pattern is incorrect. When we add small data, we should change +// this pattern to use memw(#foo). +let isMoveImm = 1 in +def CONST32 : LDInst<(outs IntRegs:$dst), (ins globaladdress:$global), + "$dst = CONST32(#$global)", + [(set IntRegs:$dst, + (load (HexagonCONST32 tglobaltlsaddr:$global)))]>; + +let isReMaterializable = 1, isMoveImm = 1 in +def CONST32_set : LDInst<(outs IntRegs:$dst), (ins globaladdress:$global), + "$dst = CONST32(#$global)", + [(set IntRegs:$dst, + (HexagonCONST32 tglobaladdr:$global))]>; + +let isReMaterializable = 1, isMoveImm = 1 in +def CONST32_set_jt : LDInst<(outs IntRegs:$dst), (ins jumptablebase:$jt), + "$dst = CONST32(#$jt)", + [(set IntRegs:$dst, + (HexagonCONST32 tjumptable:$jt))]>; + +let isReMaterializable = 1, isMoveImm = 1 in +def CONST32GP_set : LDInst<(outs IntRegs:$dst), (ins globaladdress:$global), + "$dst = CONST32(#$global)", + [(set IntRegs:$dst, + (HexagonCONST32_GP tglobaladdr:$global))]>; + +let isReMaterializable = 1, isMoveImm = 1 in +def CONST32_Int_Real : LDInst<(outs IntRegs:$dst), (ins i32imm:$global), + "$dst = CONST32(#$global)", + [(set IntRegs:$dst, imm:$global) ]>; + +let isReMaterializable = 1, isMoveImm = 1 in +def CONST32_Label : LDInst<(outs IntRegs:$dst), (ins bblabel:$label), + "$dst = CONST32($label)", + [(set IntRegs:$dst, (HexagonCONST32 bbl:$label))]>; + +let isReMaterializable = 1, isMoveImm = 1 in +def CONST64_Int_Real : LDInst<(outs DoubleRegs:$dst), (ins i64imm:$global), + "$dst = CONST64(#$global)", + [(set DoubleRegs:$dst, imm:$global) ]>; + +def TFR_PdFalse : SInst<(outs PredRegs:$dst), (ins), + "$dst = xor($dst, $dst)", + [(set PredRegs:$dst, 0)]>; + +def MPY_trsext : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + "$dst = mpy($src1, $src2)", + [(set IntRegs:$dst, + (trunc (i64 (srl (i64 (mul (i64 (sext IntRegs:$src1)), + (i64 (sext IntRegs:$src2)))), + (i32 32)))))]>; + +// Pseudo instructions. +def SDT_SPCallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i32> ]>; + +def SDT_SPCallSeqEnd : SDCallSeqEnd<[ SDTCisVT<0, i32>, + SDTCisVT<1, i32> ]>; + +def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_SPCallSeqEnd, + [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; + +def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_SPCallSeqStart, + [SDNPHasChain, SDNPOutGlue]>; + +def SDT_SPCall : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>; + +def call : SDNode<"HexagonISD::CALL", SDT_SPCall, + [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, SDNPVariadic]>; + +// For tailcalls a HexagonTCRet SDNode has 3 SDNode Properties - a chain, +// Optional Flag and Variable Arguments. +// Its 1 Operand has pointer type. +def HexagonTCRet : SDNode<"HexagonISD::TC_RETURN", SDT_SPCall, + [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; + +let Defs = [R29, R30], Uses = [R31, R30, R29] in { + def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt), + "Should never be emitted", + [(callseq_start timm:$amt)]>; +} + +let Defs = [R29, R30, R31], Uses = [R29] in { + def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), + "Should never be emitted", + [(callseq_end timm:$amt1, timm:$amt2)]>; +} +// Call subroutine. +let isCall = 1, neverHasSideEffects = 1, + Defs = [D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, + R22, R23, R28, R31, P0, P1, P2, P3, LC0, LC1, SA0, SA1] in { + def CALL : JInst<(outs), (ins calltarget:$dst, variable_ops), + "call $dst", []>; +} + +// Call subroutine from register. +let isCall = 1, neverHasSideEffects = 1, + Defs = [D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, + R22, R23, R28, R31, P0, P1, P2, P3, LC0, LC1, SA0, SA1] in { + def CALLR : JRInst<(outs), (ins IntRegs:$dst, variable_ops), + "callr $dst", + []>; + } + +// Tail Calls. +let isCall = 1, isBarrier = 1, isReturn = 1, isTerminator = 1, + Defs = [D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, + R22, R23, R28, R31, P0, P1, P2, P3, LC0, LC1, SA0, SA1] in { + def TCRETURNtg : JInst<(outs), (ins calltarget:$dst, variable_ops), + "jump $dst // TAILCALL", []>; +} +let isCall = 1, isBarrier = 1, isReturn = 1, isTerminator = 1, + Defs = [D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, + R22, R23, R28, R31, P0, P1, P2, P3, LC0, LC1, SA0, SA1] in { + def TCRETURNtext : JInst<(outs), (ins calltarget:$dst, variable_ops), + "jump $dst // TAILCALL", []>; +} + +let isCall = 1, isBarrier = 1, isReturn = 1, isTerminator = 1, + Defs = [D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, + R22, R23, R28, R31, P0, P1, P2, P3, LC0, LC1, SA0, SA1] in { + def TCRETURNR : JInst<(outs), (ins IntRegs:$dst, variable_ops), + "jumpr $dst // TAILCALL", []>; +} +// Map call instruction. +def : Pat<(call IntRegs:$dst), + (CALLR IntRegs:$dst)>, Requires<[HasV2TOnly]>; +def : Pat<(call tglobaladdr:$dst), + (CALL tglobaladdr:$dst)>, Requires<[HasV2TOnly]>; +def : Pat<(call texternalsym:$dst), + (CALL texternalsym:$dst)>, Requires<[HasV2TOnly]>; +//Tail calls. +def : Pat<(HexagonTCRet tglobaladdr:$dst), + (TCRETURNtg tglobaladdr:$dst)>; +def : Pat<(HexagonTCRet texternalsym:$dst), + (TCRETURNtext texternalsym:$dst)>; +def : Pat<(HexagonTCRet IntRegs:$dst), + (TCRETURNR IntRegs:$dst)>; + +// Map from r0 = and(r1, 65535) to r0 = zxth(r1). +def : Pat <(and IntRegs:$src1, 65535), + (ZXTH IntRegs:$src1)>; + +// Map from r0 = and(r1, 255) to r0 = zxtb(r1). +def : Pat <(and IntRegs:$src1, 255), + (ZXTB IntRegs:$src1)>; + +// Map Add(p1, true) to p1 = not(p1). +// Add(p1, false) should never be produced, +// if it does, it got to be mapped to NOOP. +def : Pat <(add PredRegs:$src1, -1), + (NOT_pp PredRegs:$src1)>; + +// Map from p0 = setlt(r0, r1) r2 = mux(p0, r3, r4) => +// p0 = cmp.lt(r0, r1), r0 = mux(p0, r2, r1). +def : Pat <(select (i1 (setlt IntRegs:$src1, IntRegs:$src2)), IntRegs:$src3, + IntRegs:$src4), + (TFR_condset_rr (CMPLTrr IntRegs:$src1, IntRegs:$src2), IntRegs:$src4, + IntRegs:$src3)>, Requires<[HasV2TOnly]>; + +// Map from p0 = pnot(p0); r0 = mux(p0, #i, #j) => r0 = mux(p0, #j, #i). +def : Pat <(select (not PredRegs:$src1), s8ImmPred:$src2, s8ImmPred:$src3), + (TFR_condset_ii PredRegs:$src1, s8ImmPred:$src3, s8ImmPred:$src2)>; + +// Map from p0 = pnot(p0); if (p0) jump => if (!p0) jump. +def : Pat <(brcond (not PredRegs:$src1), bb:$offset), + (JMP_PredNot PredRegs:$src1, bb:$offset)>; + +// Map from p2 = pnot(p2); p1 = and(p0, p2) => p1 = and(p0, !p2). +def : Pat <(and PredRegs:$src1, (not PredRegs:$src2)), + (AND_pnotp PredRegs:$src1, PredRegs:$src2)>; + +// Map from store(globaladdress + x) -> memd(#foo + x). +let AddedComplexity = 100 in +def : Pat <(store DoubleRegs:$src1, + (add (HexagonCONST32_GP tglobaladdr:$global), + u16ImmPred:$offset)), + (STrid_GP tglobaladdr:$global, u16ImmPred:$offset, DoubleRegs:$src1)>; + +// Map from store(globaladdress) -> memd(#foo + 0). +let AddedComplexity = 100 in +def : Pat <(store DoubleRegs:$src1, (HexagonCONST32_GP tglobaladdr:$global)), + (STrid_GP tglobaladdr:$global, 0, DoubleRegs:$src1)>; + +// Map from store(globaladdress + x) -> memw(#foo + x). +let AddedComplexity = 100 in +def : Pat <(store IntRegs:$src1, (add (HexagonCONST32_GP tglobaladdr:$global), + u16ImmPred:$offset)), + (STriw_GP tglobaladdr:$global, u16ImmPred:$offset, IntRegs:$src1)>; + +// Map from store(globaladdress) -> memw(#foo + 0). +let AddedComplexity = 100 in +def : Pat <(store IntRegs:$src1, (HexagonCONST32_GP tglobaladdr:$global)), + (STriw_GP tglobaladdr:$global, 0, IntRegs:$src1)>; + +// Map from store(globaladdress) -> memw(#foo + 0). +let AddedComplexity = 100 in +def : Pat <(store IntRegs:$src1, (HexagonCONST32_GP tglobaladdr:$global)), + (STriw_GP tglobaladdr:$global, 0, IntRegs:$src1)>; + +// Map from store(globaladdress + x) -> memh(#foo + x). +let AddedComplexity = 100 in +def : Pat <(truncstorei16 IntRegs:$src1, + (add (HexagonCONST32_GP tglobaladdr:$global), + u16ImmPred:$offset)), + (STrih_GP tglobaladdr:$global, u16ImmPred:$offset, IntRegs:$src1)>; + +// Map from store(globaladdress) -> memh(#foo). +let AddedComplexity = 100 in +def : Pat <(truncstorei16 IntRegs:$src1, + (HexagonCONST32_GP tglobaladdr:$global)), + (STh_GP tglobaladdr:$global, IntRegs:$src1)>; + +// Map from store(globaladdress + x) -> memb(#foo + x). +let AddedComplexity = 100 in +def : Pat <(truncstorei8 IntRegs:$src1, + (add (HexagonCONST32_GP tglobaladdr:$global), + u16ImmPred:$offset)), + (STrib_GP tglobaladdr:$global, u16ImmPred:$offset, IntRegs:$src1)>; + +// Map from store(globaladdress) -> memb(#foo). +let AddedComplexity = 100 in +def : Pat <(truncstorei8 IntRegs:$src1, + (HexagonCONST32_GP tglobaladdr:$global)), + (STb_GP tglobaladdr:$global, IntRegs:$src1)>; + +// Map from load(globaladdress + x) -> memw(#foo + x). +let AddedComplexity = 100 in +def : Pat <(load (add (HexagonCONST32_GP tglobaladdr:$global), + u16ImmPred:$offset)), + (LDriw_GP tglobaladdr:$global, u16ImmPred:$offset)>; + +// Map from load(globaladdress) -> memw(#foo + 0). +let AddedComplexity = 100 in +def : Pat <(load (HexagonCONST32_GP tglobaladdr:$global)), + (LDw_GP tglobaladdr:$global)>; + +// Map from load(globaladdress + x) -> memd(#foo + x). +let AddedComplexity = 100 in +def : Pat <(i64 (load (add (HexagonCONST32_GP tglobaladdr:$global), + u16ImmPred:$offset))), + (LDrid_GP tglobaladdr:$global, u16ImmPred:$offset)>; + +// Map from load(globaladdress) -> memw(#foo + 0). +let AddedComplexity = 100 in +def : Pat <(i64 (load (HexagonCONST32_GP tglobaladdr:$global))), + (LDd_GP tglobaladdr:$global)>; + + +// Map from Pd = load(globaladdress) -> Rd = memb(globaladdress + 0), Pd = Rd. +let AddedComplexity = 100 in +def : Pat <(i1 (load (HexagonCONST32_GP tglobaladdr:$global))), + (TFR_PdRs (LDrib_GP tglobaladdr:$global, 0))>; + +// Map from load(globaladdress + x) -> memh(#foo + x). +let AddedComplexity = 100 in +def : Pat <(sextloadi16 (add (HexagonCONST32_GP tglobaladdr:$global), + u16ImmPred:$offset)), + (LDrih_GP tglobaladdr:$global, u16ImmPred:$offset)>; + +// Map from load(globaladdress) -> memh(#foo + 0). +let AddedComplexity = 100 in +def : Pat <(sextloadi16 (HexagonCONST32_GP tglobaladdr:$global)), + (LDrih_GP tglobaladdr:$global, 0)>; + +// Map from load(globaladdress + x) -> memuh(#foo + x). +let AddedComplexity = 100 in +def : Pat <(zextloadi16 (add (HexagonCONST32_GP tglobaladdr:$global), + u16ImmPred:$offset)), + (LDriuh_GP tglobaladdr:$global, u16ImmPred:$offset)>; + +// Map from load(globaladdress) -> memuh(#foo + 0). +let AddedComplexity = 100 in +def : Pat <(zextloadi16 (HexagonCONST32_GP tglobaladdr:$global)), + (LDriuh_GP tglobaladdr:$global, 0)>; + +// Map from load(globaladdress + x) -> memuh(#foo + x). +let AddedComplexity = 100 in +def : Pat <(extloadi16 (add (HexagonCONST32_GP tglobaladdr:$global), + u16ImmPred:$offset)), + (LDriuh_GP tglobaladdr:$global, u16ImmPred:$offset)>; + +// Map from load(globaladdress) -> memuh(#foo + 0). +let AddedComplexity = 100 in +def : Pat <(extloadi16 (HexagonCONST32_GP tglobaladdr:$global)), + (LDriuh_GP tglobaladdr:$global, 0)>; +// Map from load(globaladdress + x) -> memub(#foo + x). +let AddedComplexity = 100 in +def : Pat <(zextloadi8 (add (HexagonCONST32_GP tglobaladdr:$global), + u16ImmPred:$offset)), + (LDriub_GP tglobaladdr:$global, u16ImmPred:$offset)>; + +// Map from load(globaladdress) -> memuh(#foo + 0). +let AddedComplexity = 100 in +def : Pat <(zextloadi8 (HexagonCONST32_GP tglobaladdr:$global)), + (LDriub_GP tglobaladdr:$global, 0)>; + +// Map from load(globaladdress + x) -> memb(#foo + x). +let AddedComplexity = 100 in +def : Pat <(sextloadi8 (add (HexagonCONST32_GP tglobaladdr:$global), + u16ImmPred:$offset)), + (LDrib_GP tglobaladdr:$global, u16ImmPred:$offset)>; + +// Map from load(globaladdress) -> memb(#foo). +let AddedComplexity = 100 in +def : Pat <(extloadi8 (HexagonCONST32_GP tglobaladdr:$global)), + (LDb_GP tglobaladdr:$global)>; + +// Map from load(globaladdress) -> memb(#foo). +let AddedComplexity = 100 in +def : Pat <(sextloadi8 (HexagonCONST32_GP tglobaladdr:$global)), + (LDb_GP tglobaladdr:$global)>; + +// Map from load(globaladdress) -> memub(#foo). +let AddedComplexity = 100 in +def : Pat <(zextloadi8 (HexagonCONST32_GP tglobaladdr:$global)), + (LDub_GP tglobaladdr:$global)>; + +// When the Interprocedural Global Variable optimizer realizes that a +// certain global variable takes only two constant values, it shrinks the +// global to a boolean. Catch those loads here in the following 3 patterns. +let AddedComplexity = 100 in +def : Pat <(extloadi1 (HexagonCONST32_GP tglobaladdr:$global)), + (LDb_GP tglobaladdr:$global)>; + +let AddedComplexity = 100 in +def : Pat <(sextloadi1 (HexagonCONST32_GP tglobaladdr:$global)), + (LDb_GP tglobaladdr:$global)>; + +let AddedComplexity = 100 in +def : Pat <(zextloadi1 (HexagonCONST32_GP tglobaladdr:$global)), + (LDub_GP tglobaladdr:$global)>; + +// Map from load(globaladdress) -> memh(#foo). +let AddedComplexity = 100 in +def : Pat <(extloadi16 (HexagonCONST32_GP tglobaladdr:$global)), + (LDh_GP tglobaladdr:$global)>; + +// Map from load(globaladdress) -> memh(#foo). +let AddedComplexity = 100 in +def : Pat <(sextloadi16 (HexagonCONST32_GP tglobaladdr:$global)), + (LDh_GP tglobaladdr:$global)>; + +// Map from load(globaladdress) -> memuh(#foo). +let AddedComplexity = 100 in +def : Pat <(zextloadi16 (HexagonCONST32_GP tglobaladdr:$global)), + (LDuh_GP tglobaladdr:$global)>; + +// Map from i1 loads to 32 bits. This assumes that the i1* is byte aligned. +def : Pat <(i32 (zextloadi1 ADDRriS11_0:$addr)), + (AND_rr (LDrib ADDRriS11_0:$addr), (TFRI 0x1))>; + +// Map from Rdd = sign_extend_inreg(Rss, i32) -> Rdd = SXTW(Rss.lo). +def : Pat <(i64 (sext_inreg DoubleRegs:$src1, i32)), + (i64 (SXTW (EXTRACT_SUBREG DoubleRegs:$src1, subreg_loreg)))>; + +// Map from Rdd = sign_extend_inreg(Rss, i16) -> Rdd = SXTW(SXTH(Rss.lo)). +def : Pat <(i64 (sext_inreg DoubleRegs:$src1, i16)), + (i64 (SXTW (SXTH (EXTRACT_SUBREG DoubleRegs:$src1, subreg_loreg))))>; + +// Map from Rdd = sign_extend_inreg(Rss, i8) -> Rdd = SXTW(SXTB(Rss.lo)). +def : Pat <(i64 (sext_inreg DoubleRegs:$src1, i8)), + (i64 (SXTW (SXTB (EXTRACT_SUBREG DoubleRegs:$src1, subreg_loreg))))>; + +// We want to prevent emiting pnot's as much as possible. +// Map brcond with an unsupported setcc to a JMP_PredNot. +def : Pat <(brcond (i1 (setne IntRegs:$src1, IntRegs:$src2)), bb:$offset), + (JMP_PredNot (CMPEQrr IntRegs:$src1, IntRegs:$src2), bb:$offset)>; + +def : Pat <(brcond (i1 (setne IntRegs:$src1, s10ImmPred:$src2)), bb:$offset), + (JMP_PredNot (CMPEQri IntRegs:$src1, s10ImmPred:$src2), bb:$offset)>; + +def : Pat <(brcond (i1 (setne PredRegs:$src1, (i1 -1))), bb:$offset), + (JMP_PredNot PredRegs:$src1, bb:$offset)>; + +def : Pat <(brcond (i1 (setne PredRegs:$src1, (i1 0))), bb:$offset), + (JMP_Pred PredRegs:$src1, bb:$offset)>; + +def : Pat <(brcond (i1 (setlt IntRegs:$src1, s8ImmPred:$src2)), bb:$offset), + (JMP_PredNot (CMPGEri IntRegs:$src1, s8ImmPred:$src2), bb:$offset)>; + +def : Pat <(brcond (i1 (setlt IntRegs:$src1, IntRegs:$src2)), bb:$offset), + (JMP_Pred (CMPLTrr IntRegs:$src1, IntRegs:$src2), bb:$offset)>; + +def : Pat <(brcond (i1 (setuge DoubleRegs:$src1, DoubleRegs:$src2)), + bb:$offset), + (JMP_PredNot (CMPGTU64rr DoubleRegs:$src2, DoubleRegs:$src1), + bb:$offset)>; + +def : Pat <(brcond (i1 (setule IntRegs:$src1, IntRegs:$src2)), bb:$offset), + (JMP_PredNot (CMPGTUrr IntRegs:$src1, IntRegs:$src2), bb:$offset)>; + +def : Pat <(brcond (i1 (setule DoubleRegs:$src1, DoubleRegs:$src2)), + bb:$offset), + (JMP_PredNot (CMPGTU64rr DoubleRegs:$src1, DoubleRegs:$src2), + bb:$offset)>; + +// Map from a 64-bit select to an emulated 64-bit mux. +// Hexagon does not support 64-bit MUXes; so emulate with combines. +def : Pat <(select PredRegs:$src1, DoubleRegs:$src2, DoubleRegs:$src3), + (COMBINE_rr + (MUX_rr PredRegs:$src1, + (EXTRACT_SUBREG DoubleRegs:$src2, subreg_hireg), + (EXTRACT_SUBREG DoubleRegs:$src3, subreg_hireg)), + (MUX_rr PredRegs:$src1, + (EXTRACT_SUBREG DoubleRegs:$src2, subreg_loreg), + (EXTRACT_SUBREG DoubleRegs:$src3, subreg_loreg)))>; + +// Map from a 1-bit select to logical ops. +// From LegalizeDAG.cpp: (B1 ? B2 : B3) <=> (B1 & B2)|(!B1&B3). +def : Pat <(select PredRegs:$src1, PredRegs:$src2, PredRegs:$src3), + (OR_pp (AND_pp PredRegs:$src1, PredRegs:$src2), + (AND_pp (NOT_pp PredRegs:$src1), PredRegs:$src3))>; + +// Map Pd = load(addr) -> Rs = load(addr); Pd = Rs. +def : Pat<(i1 (load ADDRriS11_2:$addr)), + (i1 (TFR_PdRs (i32 (LDrib ADDRriS11_2:$addr))))>; + +// Map for truncating from 64 immediates to 32 bit immediates. +def : Pat<(i32 (trunc DoubleRegs:$src)), + (i32 (EXTRACT_SUBREG DoubleRegs:$src, subreg_loreg))>; + +// Map for truncating from i64 immediates to i1 bit immediates. +def : Pat<(i1 (trunc DoubleRegs:$src)), + (i1 (TFR_PdRs (i32(EXTRACT_SUBREG DoubleRegs:$src, subreg_loreg))))>; + +// Map memw(Rs) = Rdd -> memw(Rs) = Rt. +def : Pat<(truncstorei8 DoubleRegs:$src, ADDRriS11_0:$addr), + (STrib ADDRriS11_0:$addr, (i32 (EXTRACT_SUBREG DoubleRegs:$src, + subreg_loreg)))>; + +// Map memh(Rs) = Rdd -> memh(Rs) = Rt. +def : Pat<(truncstorei16 DoubleRegs:$src, ADDRriS11_0:$addr), + (STrih ADDRriS11_0:$addr, (i32 (EXTRACT_SUBREG DoubleRegs:$src, + subreg_loreg)))>; + +// Map from i1 = constant<-1>; memw(addr) = i1 -> r0 = 1; memw(addr) = r0. +def : Pat<(store (i1 -1), ADDRriS11_2:$addr), + (STrib ADDRriS11_2:$addr, (TFRI 1))>; + +let AddedComplexity = 100 in +// Map from i1 = constant<-1>; memw(CONST32(#foo)) = i1 -> r0 = 1; +// memw(#foo) = r0 +def : Pat<(store (i1 -1), (HexagonCONST32_GP tglobaladdr:$global)), + (STb_GP tglobaladdr:$global, (TFRI 1))>; + + +// Map from i1 = constant<-1>; store i1 -> r0 = 1; store r0. +def : Pat<(store (i1 -1), ADDRriS11_2:$addr), + (STrib ADDRriS11_2:$addr, (TFRI 1))>; + +// Map from memb(Rs) = Pd -> Rt = mux(Pd, #0, #1); store Rt. +def : Pat<(store PredRegs:$src1, ADDRriS11_2:$addr), + (STrib ADDRriS11_2:$addr, (i32 (MUX_ii PredRegs:$src1, 1, 0)) )>; + +// Map Rdd = anyext(Rs) -> Rdd = sxtw(Rs). +// Hexagon_TODO: We can probably use combine but that will cost 2 instructions. +// Better way to do this? +def : Pat<(i64 (anyext IntRegs:$src1)), + (i64 (SXTW IntRegs:$src1))>; + +// Map cmple -> cmpgt. +// rs <= rt -> !(rs > rt). +def : Pat<(i1 (setle IntRegs:$src1, s10ImmPred:$src2)), + (i1 (NOT_Ps (CMPGTri IntRegs:$src1, s10ImmPred:$src2)))>; + +// rs <= rt -> !(rs > rt). +def : Pat<(i1 (setle IntRegs:$src1, IntRegs:$src2)), + (i1 (NOT_Ps (CMPGTrr IntRegs:$src1, IntRegs:$src2)))>; + +// Rss <= Rtt -> !(Rss > Rtt). +def : Pat<(i1 (setle DoubleRegs:$src1, DoubleRegs:$src2)), + (i1 (NOT_Ps (CMPGT64rr DoubleRegs:$src1, DoubleRegs:$src2)))>; + +// Map cmpne -> cmpeq. +// Hexagon_TODO: We should improve on this. +// rs != rt -> !(rs == rt). +def : Pat <(i1 (setne IntRegs:$src1, s10ImmPred:$src2)), + (i1 (NOT_Ps(i1 (CMPEQri IntRegs:$src1, s10ImmPred:$src2))))>; + +// Map cmpne(Rs) -> !cmpeqe(Rs). +// rs != rt -> !(rs == rt). +def : Pat <(i1 (setne IntRegs:$src1, IntRegs:$src2)), + (i1 (NOT_Ps(i1 (CMPEQrr IntRegs:$src1, IntRegs:$src2))))>; + +// Convert setne back to xor for hexagon since we compute w/ pred registers. +def : Pat <(i1 (setne PredRegs:$src1, PredRegs:$src2)), + (i1 (XOR_pp PredRegs:$src1, PredRegs:$src2))>; + +// Map cmpne(Rss) -> !cmpew(Rss). +// rs != rt -> !(rs == rt). +def : Pat <(i1 (setne DoubleRegs:$src1, DoubleRegs:$src2)), + (i1 (NOT_Ps(i1 (CMPEHexagon4rr DoubleRegs:$src1, DoubleRegs:$src2))))>; + +// Map cmpge(Rs, Rt) -> !(cmpgt(Rs, Rt). +// rs >= rt -> !(rt > rs). +def : Pat <(i1 (setge IntRegs:$src1, IntRegs:$src2)), + (i1 (NOT_Ps(i1 (CMPGTrr IntRegs:$src2, IntRegs:$src1))))>; + +def : Pat <(i1 (setge IntRegs:$src1, s8ImmPred:$src2)), + (i1 (CMPGEri IntRegs:$src1, s8ImmPred:$src2))>; + +// Map cmpge(Rss, Rtt) -> !cmpgt(Rtt, Rss). +// rss >= rtt -> !(rtt > rss). +def : Pat <(i1 (setge DoubleRegs:$src1, DoubleRegs:$src2)), + (i1 (NOT_Ps(i1 (CMPGT64rr DoubleRegs:$src2, DoubleRegs:$src1))))>; + +// Map cmplt(Rs, Imm) -> !cmpge(Rs, Imm). +// rs < rt -> !(rs >= rt). +def : Pat <(i1 (setlt IntRegs:$src1, s8ImmPred:$src2)), + (i1 (NOT_Ps (CMPGEri IntRegs:$src1, s8ImmPred:$src2)))>; + +// Map cmplt(Rs, Rt) -> cmplt(Rs, Rt). +// rs < rt -> rs < rt. Let assembler map it. +def : Pat <(i1 (setlt IntRegs:$src1, IntRegs:$src2)), + (i1 (CMPLTrr IntRegs:$src2, IntRegs:$src1))>; + +// Map cmplt(Rss, Rtt) -> cmpgt(Rtt, Rss). +// rss < rtt -> (rtt > rss). +def : Pat <(i1 (setlt DoubleRegs:$src1, DoubleRegs:$src2)), + (i1 (CMPGT64rr DoubleRegs:$src2, DoubleRegs:$src1))>; + +// Map from cmpltu(Rs, Rd) -> !cmpgtu(Rs, Rd - 1). +// rs < rt -> rt > rs. +def : Pat <(i1 (setult IntRegs:$src1, IntRegs:$src2)), + (i1 (CMPGTUrr IntRegs:$src2, IntRegs:$src1))>; + +// Map from cmpltu(Rss, Rdd) -> !cmpgtu(Rss, Rdd - 1). +// rs < rt -> rt > rs. +def : Pat <(i1 (setult DoubleRegs:$src1, DoubleRegs:$src2)), + (i1 (CMPGTU64rr DoubleRegs:$src2, DoubleRegs:$src1))>; + +// Map from Rs >= Rt -> !(Rt > Rs). +// rs >= rt -> !(rt > rs). +def : Pat <(i1 (setuge IntRegs:$src1, IntRegs:$src2)), + (i1 (NOT_Ps (CMPGTUrr IntRegs:$src2, IntRegs:$src1)))>; + +// Map from Rs >= Rt -> !(Rt > Rs). +// rs >= rt -> !(rt > rs). +def : Pat <(i1 (setuge DoubleRegs:$src1, DoubleRegs:$src2)), + (i1 (NOT_Ps (CMPGTU64rr DoubleRegs:$src2, DoubleRegs:$src1)))>; + +// Map from cmpleu(Rs, Rs) -> !cmpgtu(Rs, Rs). +// Map from (Rs <= Rt) -> !(Rs > Rt). +def : Pat <(i1 (setule IntRegs:$src1, IntRegs:$src2)), + (i1 (NOT_Ps (CMPGTUrr IntRegs:$src1, IntRegs:$src2)))>; + +// Map from cmpleu(Rss, Rtt) -> !cmpgtu(Rss, Rtt-1). +// Map from (Rs <= Rt) -> !(Rs > Rt). +def : Pat <(i1 (setule DoubleRegs:$src1, DoubleRegs:$src2)), + (i1 (NOT_Ps (CMPGTU64rr DoubleRegs:$src1, DoubleRegs:$src2)))>; + +// Sign extends. +// i1 -> i32 +def : Pat <(i32 (sext PredRegs:$src1)), + (i32 (MUX_ii PredRegs:$src1, -1, 0))>; + +// Convert sign-extended load back to load and sign extend. +// i8 -> i64 +def: Pat <(i64 (sextloadi8 ADDRriS11_0:$src1)), + (i64 (SXTW (LDrib ADDRriS11_0:$src1)))>; + +// Convert any-extended load back to load and sign extend. +// i8 -> i64 +def: Pat <(i64 (extloadi8 ADDRriS11_0:$src1)), + (i64 (SXTW (LDrib ADDRriS11_0:$src1)))>; + +// Convert sign-extended load back to load and sign extend. +// i16 -> i64 +def: Pat <(i64 (sextloadi16 ADDRriS11_1:$src1)), + (i64 (SXTW (LDrih ADDRriS11_1:$src1)))>; + +// Convert sign-extended load back to load and sign extend. +// i32 -> i64 +def: Pat <(i64 (sextloadi32 ADDRriS11_2:$src1)), + (i64 (SXTW (LDriw ADDRriS11_2:$src1)))>; + + +// Zero extends. +// i1 -> i32 +def : Pat <(i32 (zext PredRegs:$src1)), + (i32 (MUX_ii PredRegs:$src1, 1, 0))>; + +// i1 -> i64 +def : Pat <(i64 (zext PredRegs:$src1)), + (i64 (COMBINE_rr (TFRI 0), (MUX_ii PredRegs:$src1, 1, 0)))>; + +// i32 -> i64 +def : Pat <(i64 (zext IntRegs:$src1)), + (i64 (COMBINE_rr (TFRI 0), IntRegs:$src1))>; + +// i8 -> i64 +def: Pat <(i64 (zextloadi8 ADDRriS11_0:$src1)), + (i64 (COMBINE_rr (TFRI 0), (LDriub ADDRriS11_0:$src1)))>; + +// i16 -> i64 +def: Pat <(i64 (zextloadi16 ADDRriS11_1:$src1)), + (i64 (COMBINE_rr (TFRI 0), (LDriuh ADDRriS11_1:$src1)))>; + +// i32 -> i64 +def: Pat <(i64 (zextloadi32 ADDRriS11_2:$src1)), + (i64 (COMBINE_rr (TFRI 0), (LDriw ADDRriS11_2:$src1)))>; + +def: Pat <(i32 (zextloadi1 ADDRriS11_0:$src1)), + (i32 (LDriw ADDRriS11_0:$src1))>; + +// Map from Rs = Pd to Pd = mux(Pd, #1, #0) +def : Pat <(i32 (zext PredRegs:$src1)), + (i32 (MUX_ii PredRegs:$src1, 1, 0))>; + +// Map from Rs = Pd to Pd = mux(Pd, #1, #0) +def : Pat <(i32 (anyext PredRegs:$src1)), + (i32 (MUX_ii PredRegs:$src1, 1, 0))>; + +// Map from Rss = Pd to Rdd = sxtw (mux(Pd, #1, #0)) +def : Pat <(i64 (anyext PredRegs:$src1)), + (i64 (SXTW (i32 (MUX_ii PredRegs:$src1, 1, 0))))>; + + +// Any extended 64-bit load. +// anyext i32 -> i64 +def: Pat <(i64 (extloadi32 ADDRriS11_2:$src1)), + (i64 (COMBINE_rr (TFRI 0), (LDriw ADDRriS11_2:$src1)))>; + +// anyext i16 -> i64. +def: Pat <(i64 (extloadi16 ADDRriS11_2:$src1)), + (i64 (COMBINE_rr (TFRI 0), (LDrih ADDRriS11_2:$src1)))>; + +// Map from Rdd = zxtw(Rs) -> Rdd = combine(0, Rs). +def : Pat<(i64 (zext IntRegs:$src1)), + (i64 (COMBINE_rr (TFRI 0), IntRegs:$src1))>; + +// Multiply 64-bit unsigned and use upper result. +def : Pat <(mulhu DoubleRegs:$src1, DoubleRegs:$src2), + (MPYU64_acc(COMBINE_rr (TFRI 0), + (EXTRACT_SUBREG + (LSRd_ri(MPYU64_acc(MPYU64_acc(COMBINE_rr (TFRI 0), + (EXTRACT_SUBREG (LSRd_ri(MPYU64 + (EXTRACT_SUBREG DoubleRegs:$src1, + subreg_loreg), + (EXTRACT_SUBREG DoubleRegs:$src2, + subreg_loreg)), + 32) ,subreg_loreg)), + (EXTRACT_SUBREG DoubleRegs:$src1, + subreg_hireg), + (EXTRACT_SUBREG DoubleRegs:$src2, + subreg_loreg)), + (EXTRACT_SUBREG DoubleRegs:$src1, subreg_loreg), + (EXTRACT_SUBREG DoubleRegs:$src2, subreg_hireg)), + 32),subreg_loreg)), + (EXTRACT_SUBREG DoubleRegs:$src1, subreg_hireg), + (EXTRACT_SUBREG DoubleRegs:$src2, subreg_hireg) + )>; + +// Multiply 64-bit signed and use upper result. +def : Pat <(mulhs DoubleRegs:$src1, DoubleRegs:$src2), + (MPY64_acc(COMBINE_rr (TFRI 0), + (EXTRACT_SUBREG + (LSRd_ri(MPY64_acc(MPY64_acc(COMBINE_rr (TFRI 0), + (EXTRACT_SUBREG (LSRd_ri(MPYU64 + (EXTRACT_SUBREG DoubleRegs:$src1, + subreg_loreg), + (EXTRACT_SUBREG DoubleRegs:$src2, + subreg_loreg)), + 32) ,subreg_loreg)), + (EXTRACT_SUBREG DoubleRegs:$src1, + subreg_hireg), + (EXTRACT_SUBREG DoubleRegs:$src2, + subreg_loreg)), + (EXTRACT_SUBREG DoubleRegs:$src1, subreg_loreg), + (EXTRACT_SUBREG DoubleRegs:$src2, subreg_hireg)), + 32),subreg_loreg)), + (EXTRACT_SUBREG DoubleRegs:$src1, subreg_hireg), + (EXTRACT_SUBREG DoubleRegs:$src2, subreg_hireg) + )>; + +// Hexagon specific ISD nodes. +def SDTHexagonADJDYNALLOC : SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>]>; +def Hexagon_ADJDYNALLOC : SDNode<"HexagonISD::ADJDYNALLOC", + SDTHexagonADJDYNALLOC>; +// Needed to tag these instructions for stack layout. +let usesCustomInserter = 1 in +def ADJDYNALLOC : ALU32_ri<(outs IntRegs:$dst), (ins IntRegs:$src1, + s16Imm:$src2), + "$dst = add($src1, #$src2)", + [(set IntRegs:$dst, (Hexagon_ADJDYNALLOC IntRegs:$src1, + s16ImmPred:$src2))]>; + +def SDTHexagonARGEXTEND : SDTypeProfile<1, 1, []>; +def Hexagon_ARGEXTEND : SDNode<"HexagonISD::ARGEXTEND", SDTHexagonARGEXTEND>; +def ARGEXTEND : ALU32_rr <(outs IntRegs:$dst), (ins IntRegs:$src1), + "$dst = $src1", + [(set IntRegs:$dst, (Hexagon_ARGEXTEND IntRegs:$src1))]>; + +let AddedComplexity = 100 in +def : Pat<(i32 (sext_inreg (Hexagon_ARGEXTEND IntRegs:$src1), i16)), + (TFR IntRegs:$src1)>; + + +def SDHexagonBR_JT: SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>; +def HexagonBR_JT: SDNode<"HexagonISD::BR_JT", SDHexagonBR_JT, [SDNPHasChain]>; + +let isBranch=1, isIndirectBranch=1, isTerminator=1, isBarrier = 1 in +def BR_JT : JRInst<(outs), (ins IntRegs:$src), + "jumpr $src", + [(HexagonBR_JT IntRegs:$src)]>; +def HexagonWrapperJT: SDNode<"HexagonISD::WrapperJT", SDTIntUnaryOp>; + +def : Pat<(HexagonWrapperJT tjumptable:$dst), + (CONST32_set_jt tjumptable:$dst)>; + + +//===----------------------------------------------------------------------===// +// V3 Instructions + +//===----------------------------------------------------------------------===// + +include "HexagonInstrInfoV3.td" + +//===----------------------------------------------------------------------===// +// V3 Instructions - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// V4 Instructions + +//===----------------------------------------------------------------------===// + +include "HexagonInstrInfoV4.td" diff --git a/lib/Target/Hexagon/HexagonInstrInfoV3.td b/lib/Target/Hexagon/HexagonInstrInfoV3.td new file mode 100644 index 0000000000..a73897ee34 --- /dev/null +++ b/lib/Target/Hexagon/HexagonInstrInfoV3.td @@ -0,0 +1,134 @@ +//=- HexagonInstrInfoV3.td - Target Desc. for Hexagon Target -*- tablegen -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the Hexagon V3 instructions in TableGen format. +// +//===----------------------------------------------------------------------===// + + +//===----------------------------------------------------------------------===// +// J + +//===----------------------------------------------------------------------===// +// Call subroutine. +let isCall = 1, neverHasSideEffects = 1, + Defs = [D0, D1, D2, D3, D4, D5, D6, D7, R28, R31, + P0, P1, P2, P3, LC0, LC1, SA0, SA1] in { + def CALLv3 : JInst<(outs), (ins calltarget:$dst, variable_ops), + "call $dst", []>, Requires<[HasV3T]>; +} + +//===----------------------------------------------------------------------===// +// J - +//===----------------------------------------------------------------------===// + + +//===----------------------------------------------------------------------===// +// JR + +//===----------------------------------------------------------------------===// +// Call subroutine from register. +let isCall = 1, neverHasSideEffects = 1, + Defs = [D0, D1, D2, D3, D4, D5, D6, D7, R28, R31, + P0, P1, P2, P3, LC0, LC1, SA0, SA1] in { + def CALLRv3 : JRInst<(outs), (ins IntRegs:$dst, variable_ops), + "callr $dst", + []>, Requires<[HasV3TOnly]>; + } + + +// if(p?.new) jumpr:t r? +let isReturn = 1, isTerminator = 1, isBarrier = 1, + Defs = [PC], Uses = [R31] in { + def JMPR_cPnewt: JRInst<(outs), (ins PredRegs:$src1, IntRegs:$src2), + "if ($src1.new) jumpr:t $src2", + []>, Requires<[HasV3T]>; +} + +// if (!p?.new) jumpr:t r? +let isReturn = 1, isTerminator = 1, isBarrier = 1, + Defs = [PC], Uses = [R31] in { + def JMPR_cNotPnewt: JRInst<(outs), (ins PredRegs:$src1, IntRegs:$src2), + "if (!$src1.new) jumpr:t $src2", + []>, Requires<[HasV3T]>; +} + +// Not taken. +// if(p?.new) jumpr:nt r? +let isReturn = 1, isTerminator = 1, isBarrier = 1, + Defs = [PC], Uses = [R31] in { + def JMPR_cPnewNt: JRInst<(outs), (ins PredRegs:$src1, IntRegs:$src2), + "if ($src1.new) jumpr:nt $src2", + []>, Requires<[HasV3T]>; +} + +// if (!p?.new) jumpr:nt r? +let isReturn = 1, isTerminator = 1, isBarrier = 1, + Defs = [PC], Uses = [R31] in { + def JMPR_cNotPnewNt: JRInst<(outs), (ins PredRegs:$src1, IntRegs:$src2), + "if (!$src1.new) jumpr:nt $src2", + []>, Requires<[HasV3T]>; +} + +//===----------------------------------------------------------------------===// +// JR - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// ALU64/ALU + +//===----------------------------------------------------------------------===// + +let AddedComplexity = 200 in +def MAXw_dd : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, + DoubleRegs:$src2), + "$dst = max($src2, $src1)", + [(set DoubleRegs:$dst, (select (i1 (setlt DoubleRegs:$src2, + DoubleRegs:$src1)), + DoubleRegs:$src1, + DoubleRegs:$src2))]>, +Requires<[HasV3T]>; + +let AddedComplexity = 200 in +def MINw_dd : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, + DoubleRegs:$src2), + "$dst = min($src2, $src1)", + [(set DoubleRegs:$dst, (select (i1 (setgt DoubleRegs:$src2, + DoubleRegs:$src1)), + DoubleRegs:$src1, + DoubleRegs:$src2))]>, +Requires<[HasV3T]>; + +//===----------------------------------------------------------------------===// +// ALU64/ALU - +//===----------------------------------------------------------------------===// + + + + +//def : Pat <(brcond (i1 (seteq IntRegs:$src1, 0)), bb:$offset), +// (JMP_RegEzt IntRegs:$src1, bb:$offset)>, Requires<[HasV3T]>; + +//def : Pat <(brcond (i1 (setne IntRegs:$src1, 0)), bb:$offset), +// (JMP_RegNzt IntRegs:$src1, bb:$offset)>, Requires<[HasV3T]>; + +//def : Pat <(brcond (i1 (setle IntRegs:$src1, 0)), bb:$offset), +// (JMP_RegLezt IntRegs:$src1, bb:$offset)>, Requires<[HasV3T]>; + +//def : Pat <(brcond (i1 (setge IntRegs:$src1, 0)), bb:$offset), +// (JMP_RegGezt IntRegs:$src1, bb:$offset)>, Requires<[HasV3T]>; + +//def : Pat <(brcond (i1 (setgt IntRegs:$src1, -1)), bb:$offset), +// (JMP_RegGezt IntRegs:$src1, bb:$offset)>, Requires<[HasV3T]>; + + +// Map call instruction +def : Pat<(call IntRegs:$dst), + (CALLRv3 IntRegs:$dst)>, Requires<[HasV3T]>; +def : Pat<(call tglobaladdr:$dst), + (CALLv3 tglobaladdr:$dst)>, Requires<[HasV3T]>; +def : Pat<(call texternalsym:$dst), + (CALLv3 texternalsym:$dst)>, Requires<[HasV3T]>; diff --git a/lib/Target/Hexagon/HexagonInstrInfoV4.td b/lib/Target/Hexagon/HexagonInstrInfoV4.td new file mode 100644 index 0000000000..24218d0e33 --- /dev/null +++ b/lib/Target/Hexagon/HexagonInstrInfoV4.td @@ -0,0 +1,3392 @@ +//=- HexagonInstrInfoV4.td - Target Desc. for Hexagon Target -*- tablegen -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the Hexagon V4 instructions in TableGen format. +// +//===----------------------------------------------------------------------===// + +// Hexagon V4 Architecture spec defines 8 instruction classes: +// LD ST ALU32 XTYPE J JR MEMOP NV CR SYSTEM(system is not implemented in the +// compiler) + +// LD Instructions: +// ======================================== +// Loads (8/16/32/64 bit) +// Deallocframe + +// ST Instructions: +// ======================================== +// Stores (8/16/32/64 bit) +// Allocframe + +// ALU32 Instructions: +// ======================================== +// Arithmetic / Logical (32 bit) +// Vector Halfword + +// XTYPE Instructions (32/64 bit): +// ======================================== +// Arithmetic, Logical, Bit Manipulation +// Multiply (Integer, Fractional, Complex) +// Permute / Vector Permute Operations +// Predicate Operations +// Shift / Shift with Add/Sub/Logical +// Vector Byte ALU +// Vector Halfword (ALU, Shift, Multiply) +// Vector Word (ALU, Shift) + +// J Instructions: +// ======================================== +// Jump/Call PC-relative + +// JR Instructions: +// ======================================== +// Jump/Call Register + +// MEMOP Instructions: +// ======================================== +// Operation on memory (8/16/32 bit) + +// NV Instructions: +// ======================================== +// New-value Jumps +// New-value Stores + +// CR Instructions: +// ======================================== +// Control-Register Transfers +// Hardware Loop Setup +// Predicate Logicals & Reductions + +// SYSTEM Instructions (not implemented in the compiler): +// ======================================== +// Prefetch +// Cache Maintenance +// Bus Operations + + +//===----------------------------------------------------------------------===// +// ALU32 + +//===----------------------------------------------------------------------===// + +// Shift halfword. + +def ASLH_cPt_V4 : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2), + "if ($src1) $dst = aslh($src2)", + []>, + Requires<[HasV4T]>; + +def ASLH_cNotPt_V4 : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2), + "if (!$src1) $dst = aslh($src2)", + []>, + Requires<[HasV4T]>; + +def ASLH_cdnPt_V4 : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2), + "if ($src1.new) $dst = aslh($src2)", + []>, + Requires<[HasV4T]>; + +def ASLH_cdnNotPt_V4 : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2), + "if (!$src1.new) $dst = aslh($src2)", + []>, + Requires<[HasV4T]>; + +def ASRH_cPt_V4 : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2), + "if ($src1) $dst = asrh($src2)", + []>, + Requires<[HasV4T]>; + +def ASRH_cNotPt_V4 : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2), + "if (!$src1) $dst = asrh($src2)", + []>, + Requires<[HasV4T]>; + +def ASRH_cdnPt_V4 : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2), + "if ($src1.new) $dst = asrh($src2)", + []>, + Requires<[HasV4T]>; + +def ASRH_cdnNotPt_V4 : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2), + "if (!$src1.new) $dst = asrh($src2)", + []>, + Requires<[HasV4T]>; + +// Sign extend. + +def SXTB_cPt_V4 : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2), + "if ($src1) $dst = sxtb($src2)", + []>, + Requires<[HasV4T]>; + +def SXTB_cNotPt_V4 : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2), + "if (!$src1) $dst = sxtb($src2)", + []>, + Requires<[HasV4T]>; + +def SXTB_cdnPt_V4 : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2), + "if ($src1.new) $dst = sxtb($src2)", + []>, + Requires<[HasV4T]>; + +def SXTB_cdnNotPt_V4 : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2), + "if (!$src1.new) $dst = sxtb($src2)", + []>, + Requires<[HasV4T]>; + + +def SXTH_cPt_V4 : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2), + "if ($src1) $dst = sxth($src2)", + []>, + Requires<[HasV4T]>; + +def SXTH_cNotPt_V4 : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2), + "if (!$src1) $dst = sxth($src2)", + []>, + Requires<[HasV4T]>; + +def SXTH_cdnPt_V4 : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2), + "if ($src1.new) $dst = sxth($src2)", + []>, + Requires<[HasV4T]>; + +def SXTH_cdnNotPt_V4 : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2), + "if (!$src1.new) $dst = sxth($src2)", + []>, + Requires<[HasV4T]>; + +// Zero exten. + +let neverHasSideEffects = 1 in +def ZXTB_cPt_V4 : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2), + "if ($src1) $dst = zxtb($src2)", + []>, + Requires<[HasV4T]>; + +let neverHasSideEffects = 1 in +def ZXTB_cNotPt_V4 : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2), + "if (!$src1) $dst = zxtb($src2)", + []>, + Requires<[HasV4T]>; + +let neverHasSideEffects = 1 in +def ZXTB_cdnPt_V4 : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2), + "if ($src1.new) $dst = zxtb($src2)", + []>, + Requires<[HasV4T]>; + +let neverHasSideEffects = 1 in +def ZXTB_cdnNotPt_V4 : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2), + "if (!$src1.new) $dst = zxtb($src2)", + []>, + Requires<[HasV4T]>; + +let neverHasSideEffects = 1 in +def ZXTH_cPt_V4 : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2), + "if ($src1) $dst = zxth($src2)", + []>, + Requires<[HasV4T]>; + +let neverHasSideEffects = 1 in +def ZXTH_cNotPt_V4 : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2), + "if (!$src1) $dst = zxth($src2)", + []>, + Requires<[HasV4T]>; + +let neverHasSideEffects = 1 in +def ZXTH_cdnPt_V4 : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2), + "if ($src1.new) $dst = zxth($src2)", + []>, + Requires<[HasV4T]>; + +let neverHasSideEffects = 1 in +def ZXTH_cdnNotPt_V4 : ALU32_rr<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2), + "if (!$src1.new) $dst = zxth($src2)", + []>, + Requires<[HasV4T]>; + + +//===----------------------------------------------------------------------===// +// ALU32 - +//===----------------------------------------------------------------------===// + + + +//===----------------------------------------------------------------------===// +// LD + +//===----------------------------------------------------------------------===// +/// +/// Make sure that in post increment load, the first operand is always the post +/// increment operand. +/// +//// Load doubleword. +// Rdd=memd(Re=#U6) + +// Rdd=memd(Rs+Rt<<#u2) +// Special case pattern for indexed load without offset which is easier to +// match. AddedComplexity of this pattern should be lower than base+offset load +// and lower yet than the more generic version with offset/shift below +// Similar approach is taken for all other base+index loads. +let AddedComplexity = 10, isPredicable = 1 in +def LDrid_indexed_V4 : LDInst<(outs DoubleRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2), + "$dst=memd($src1+$src2<<#0)", + [(set DoubleRegs:$dst, (load (add IntRegs:$src1, + IntRegs:$src2)))]>, + Requires<[HasV4T]>; + +let AddedComplexity = 40, isPredicable = 1 in +def LDrid_indexed_shl_V4 : LDInst<(outs DoubleRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$offset), + "$dst=memd($src1+$src2<<#$offset)", + [(set DoubleRegs:$dst, (load (add IntRegs:$src1, + (shl IntRegs:$src2, + u2ImmPred:$offset))))]>, + Requires<[HasV4T]>; + +//// Load doubleword conditionally. +// if ([!]Pv[.new]) Rd=memd(Rs+Rt<<#u2) +// if (Pv) Rd=memd(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 15 in +def LDrid_indexed_cPt_V4 : LDInst<(outs DoubleRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if ($src1) $dst=memd($src2+$src3<<#0)", + []>, + Requires<[HasV4T]>; + +// if (Pv.new) Rd=memd(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 15 in +def LDrid_indexed_cdnPt_V4 : LDInst<(outs DoubleRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if ($src1.new) $dst=memd($src2+$src3<<#0)", + []>, + Requires<[HasV4T]>; + +// if (!Pv) Rd=memd(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 15 in +def LDrid_indexed_cNotPt_V4 : LDInst<(outs DoubleRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if (!$src1) $dst=memd($src2+$src3<<#0)", + []>, + Requires<[HasV4T]>; + +// if (!Pv.new) Rd=memd(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 15 in +def LDrid_indexed_cdnNotPt_V4 : LDInst<(outs DoubleRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if (!$src1.new) $dst=memd($src2+$src3<<#0)", + []>, + Requires<[HasV4T]>; + +// if (Pv) Rd=memd(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 45 in +def LDrid_indexed_shl_cPt_V4 : LDInst<(outs DoubleRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, + u2Imm:$offset), + "if ($src1) $dst=memd($src2+$src3<<#$offset)", + []>, + Requires<[HasV4T]>; + +// if (Pv.new) Rd=memd(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 45 in +def LDrid_indexed_shl_cdnPt_V4 : LDInst<(outs DoubleRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, + u2Imm:$offset), + "if ($src1.new) $dst=memd($src2+$src3<<#$offset)", + []>, + Requires<[HasV4T]>; + +// if (!Pv) Rd=memd(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 45 in +def LDrid_indexed_shl_cNotPt_V4 : LDInst<(outs DoubleRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, + u2Imm:$offset), + "if (!$src1) $dst=memd($src2+$src3<<#$offset)", + []>, + Requires<[HasV4T]>; + +// if (!Pv.new) Rd=memd(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 45 in +def LDrid_indexed_shl_cdnNotPt_V4 : LDInst<(outs DoubleRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, + u2Imm:$offset), + "if (!$src1.new) $dst=memd($src2+$src3<<#$offset)", + []>, + Requires<[HasV4T]>; + +// Rdd=memd(Rt<<#u2+#U6) + +//// Load byte. +// Rd=memb(Re=#U6) + +// Rd=memb(Rs+Rt<<#u2) +let AddedComplexity = 10, isPredicable = 1 in +def LDrib_indexed_V4 : LDInst<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2), + "$dst=memb($src1+$src2<<#0)", + [(set IntRegs:$dst, (sextloadi8 (add IntRegs:$src1, + IntRegs:$src2)))]>, + Requires<[HasV4T]>; + +let AddedComplexity = 10, isPredicable = 1 in +def LDriub_indexed_V4 : LDInst<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2), + "$dst=memub($src1+$src2<<#0)", + [(set IntRegs:$dst, (zextloadi8 (add IntRegs:$src1, + IntRegs:$src2)))]>, + Requires<[HasV4T]>; + +let AddedComplexity = 10, isPredicable = 1 in +def LDriub_ae_indexed_V4 : LDInst<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2), + "$dst=memub($src1+$src2<<#0)", + [(set IntRegs:$dst, (extloadi8 (add IntRegs:$src1, + IntRegs:$src2)))]>, + Requires<[HasV4T]>; + +let AddedComplexity = 40, isPredicable = 1 in +def LDrib_indexed_shl_V4 : LDInst<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$offset), + "$dst=memb($src1+$src2<<#$offset)", + [(set IntRegs:$dst, + (sextloadi8 (add IntRegs:$src1, + (shl IntRegs:$src2, + u2ImmPred:$offset))))]>, + Requires<[HasV4T]>; + +let AddedComplexity = 40, isPredicable = 1 in +def LDriub_indexed_shl_V4 : LDInst<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$offset), + "$dst=memub($src1+$src2<<#$offset)", + [(set IntRegs:$dst, + (zextloadi8 (add IntRegs:$src1, + (shl IntRegs:$src2, + u2ImmPred:$offset))))]>, + Requires<[HasV4T]>; + +let AddedComplexity = 40, isPredicable = 1 in +def LDriub_ae_indexed_shl_V4 : LDInst<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$offset), + "$dst=memub($src1+$src2<<#$offset)", + [(set IntRegs:$dst, (extloadi8 (add IntRegs:$src1, + (shl IntRegs:$src2, + u2ImmPred:$offset))))]>, + Requires<[HasV4T]>; + +//// Load byte conditionally. +// if ([!]Pv[.new]) Rd=memb(Rs+Rt<<#u2) +// if (Pv) Rd=memb(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 15 in +def LDrib_indexed_cPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if ($src1) $dst=memb($src2+$src3<<#0)", + []>, + Requires<[HasV4T]>; + +// if (Pv.new) Rd=memb(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 15 in +def LDrib_indexed_cdnPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if ($src1.new) $dst=memb($src2+$src3<<#0)", + []>, + Requires<[HasV4T]>; + +// if (!Pv) Rd=memb(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 15 in +def LDrib_indexed_cNotPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if (!$src1) $dst=memb($src2+$src3<<#0)", + []>, + Requires<[HasV4T]>; + +// if (!Pv.new) Rd=memb(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 15 in +def LDrib_indexed_cdnNotPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if (!$src1.new) $dst=memb($src2+$src3<<#0)", + []>, + Requires<[HasV4T]>; + +// if (Pv) Rd=memb(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 45 in +def LDrib_indexed_shl_cPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, + u2Imm:$offset), + "if ($src1) $dst=memb($src2+$src3<<#$offset)", + []>, + Requires<[HasV4T]>; + +// if (Pv.new) Rd=memb(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 45 in +def LDrib_indexed_shl_cdnPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, + u2Imm:$offset), + "if ($src1.new) $dst=memb($src2+$src3<<#$offset)", + []>, + Requires<[HasV4T]>; + +// if (!Pv) Rd=memb(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 45 in +def LDrib_indexed_shl_cNotPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, + u2Imm:$offset), + "if (!$src1) $dst=memb($src2+$src3<<#$offset)", + []>, + Requires<[HasV4T]>; + +// if (!Pv.new) Rd=memb(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 45 in +def LDrib_indexed_shl_cdnNotPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, + u2Imm:$offset), + "if (!$src1.new) $dst=memb($src2+$src3<<#$offset)", + []>, + Requires<[HasV4T]>; + +//// Load unsigned byte conditionally. +// if ([!]Pv[.new]) Rd=memub(Rs+Rt<<#u2) +// if (Pv) Rd=memub(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 15 in +def LDriub_indexed_cPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if ($src1) $dst=memub($src2+$src3<<#0)", + []>, + Requires<[HasV4T]>; + +// if (Pv.new) Rd=memub(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 15 in +def LDriub_indexed_cdnPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if ($src1.new) $dst=memub($src2+$src3<<#0)", + []>, + Requires<[HasV4T]>; + +// if (!Pv) Rd=memub(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 15 in +def LDriub_indexed_cNotPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if (!$src1) $dst=memub($src2+$src3<<#0)", + []>, + Requires<[HasV4T]>; + +// if (!Pv.new) Rd=memub(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 15 in +def LDriub_indexed_cdnNotPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if (!$src1.new) $dst=memub($src2+$src3<<#0)", + []>, + Requires<[HasV4T]>; + +// if (Pv) Rd=memub(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 45 in +def LDriub_indexed_shl_cPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, + u2Imm:$offset), + "if ($src1) $dst=memub($src2+$src3<<#$offset)", + []>, + Requires<[HasV4T]>; + +// if (Pv.new) Rd=memub(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 45 in +def LDriub_indexed_shl_cdnPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, + u2Imm:$offset), + "if ($src1.new) $dst=memub($src2+$src3<<#$offset)", + []>, + Requires<[HasV4T]>; + +// if (!Pv) Rd=memub(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 45 in +def LDriub_indexed_shl_cNotPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, + u2Imm:$offset), + "if (!$src1) $dst=memub($src2+$src3<<#$offset)", + []>, + Requires<[HasV4T]>; + +// if (!Pv.new) Rd=memub(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 45 in +def LDriub_indexed_shl_cdnNotPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, + u2Imm:$offset), + "if (!$src1.new) $dst=memub($src2+$src3<<#$offset)", + []>, + Requires<[HasV4T]>; + +// Rd=memb(Rt<<#u2+#U6) + +//// Load halfword +// Rd=memh(Re=#U6) + +// Rd=memh(Rs+Rt<<#u2) +let AddedComplexity = 10, isPredicable = 1 in +def LDrih_indexed_V4 : LDInst<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2), + "$dst=memh($src1+$src2<<#0)", + [(set IntRegs:$dst, (sextloadi16 (add IntRegs:$src1, + IntRegs:$src2)))]>, + Requires<[HasV4T]>; + +let AddedComplexity = 10, isPredicable = 1 in +def LDriuh_indexed_V4 : LDInst<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2), + "$dst=memuh($src1+$src2<<#0)", + [(set IntRegs:$dst, (zextloadi16 (add IntRegs:$src1, + IntRegs:$src2)))]>, + Requires<[HasV4T]>; + +let AddedComplexity = 10, isPredicable = 1 in +def LDriuh_ae_indexed_V4 : LDInst<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2), + "$dst=memuh($src1+$src2<<#0)", + [(set IntRegs:$dst, (extloadi16 (add IntRegs:$src1, + IntRegs:$src2)))]>, + Requires<[HasV4T]>; + +// Rd=memh(Rs+Rt<<#u2) +let AddedComplexity = 40, isPredicable = 1 in +def LDrih_indexed_shl_V4 : LDInst<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$offset), + "$dst=memh($src1+$src2<<#$offset)", + [(set IntRegs:$dst, + (sextloadi16 (add IntRegs:$src1, + (shl IntRegs:$src2, + u2ImmPred:$offset))))]>, + Requires<[HasV4T]>; + +let AddedComplexity = 40, isPredicable = 1 in +def LDriuh_indexed_shl_V4 : LDInst<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$offset), + "$dst=memuh($src1+$src2<<#$offset)", + [(set IntRegs:$dst, + (zextloadi16 (add IntRegs:$src1, + (shl IntRegs:$src2, + u2ImmPred:$offset))))]>, + Requires<[HasV4T]>; + +let AddedComplexity = 40, isPredicable = 1 in +def LDriuh_ae_indexed_shl_V4 : LDInst<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$offset), + "$dst=memuh($src1+$src2<<#$offset)", + [(set IntRegs:$dst, + (extloadi16 (add IntRegs:$src1, + (shl IntRegs:$src2, + u2ImmPred:$offset))))]>, + Requires<[HasV4T]>; + +//// Load halfword conditionally. +// if ([!]Pv[.new]) Rd=memh(Rs+Rt<<#u2) +// if (Pv) Rd=memh(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 15 in +def LDrih_indexed_cPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if ($src1) $dst=memh($src2+$src3<<#0)", + []>, + Requires<[HasV4T]>; + +// if (Pv.new) Rd=memh(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 15 in +def LDrih_indexed_cdnPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if ($src1.new) $dst=memh($src2+$src3<<#0)", + []>, + Requires<[HasV4T]>; + +// if (!Pv) Rd=memh(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 15 in +def LDrih_indexed_cNotPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if (!$src1) $dst=memh($src2+$src3<<#0)", + []>, + Requires<[HasV4T]>; + +// if (!Pv.new) Rd=memh(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 15 in +def LDrih_indexed_cdnNotPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if (!$src1.new) $dst=memh($src2+$src3<<#0)", + []>, + Requires<[HasV4T]>; + +// if (Pv) Rd=memh(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 45 in +def LDrih_indexed_shl_cPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, + u2Imm:$offset), + "if ($src1) $dst=memh($src2+$src3<<#$offset)", + []>, + Requires<[HasV4T]>; + +// if (Pv.new) Rd=memh(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 45 in +def LDrih_indexed_shl_cdnPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, + u2Imm:$offset), + "if ($src1.new) $dst=memh($src2+$src3<<#$offset)", + []>, + Requires<[HasV4T]>; + +// if (!Pv) Rd=memh(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 45 in +def LDrih_indexed_shl_cNotPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, + u2Imm:$offset), + "if (!$src1) $dst=memh($src2+$src3<<#$offset)", + []>, + Requires<[HasV4T]>; + +// if (!Pv.new) Rd=memh(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 45 in +def LDrih_indexed_shl_cdnNotPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, + u2Imm:$offset), + "if (!$src1.new) $dst=memh($src2+$src3<<#$offset)", + []>, + Requires<[HasV4T]>; + +//// Load unsigned halfword conditionally. +// if ([!]Pv[.new]) Rd=memuh(Rs+Rt<<#u2) +// if (Pv) Rd=memuh(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 15 in +def LDriuh_indexed_cPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if ($src1) $dst=memuh($src2+$src3<<#0)", + []>, + Requires<[HasV4T]>; + +// if (Pv.new) Rd=memuh(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 15 in +def LDriuh_indexed_cdnPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if ($src1.new) $dst=memuh($src2+$src3<<#0)", + []>, + Requires<[HasV4T]>; + +// if (!Pv) Rd=memuh(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 15 in +def LDriuh_indexed_cNotPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if (!$src1) $dst=memuh($src2+$src3<<#0)", + []>, + Requires<[HasV4T]>; + +// if (!Pv.new) Rd=memuh(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 15 in +def LDriuh_indexed_cdnNotPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if (!$src1.new) $dst=memuh($src2+$src3<<#0)", + []>, + Requires<[HasV4T]>; + +// if (Pv) Rd=memuh(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 45 in +def LDriuh_indexed_shl_cPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, + u2Imm:$offset), + "if ($src1) $dst=memuh($src2+$src3<<#$offset)", + []>, + Requires<[HasV4T]>; + +// if (Pv.new) Rd=memuh(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 45 in +def LDriuh_indexed_shl_cdnPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, + u2Imm:$offset), + "if ($src1.new) $dst=memuh($src2+$src3<<#$offset)", + []>, + Requires<[HasV4T]>; + +// if (!Pv) Rd=memuh(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 45 in +def LDriuh_indexed_shl_cNotPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, + u2Imm:$offset), + "if (!$src1) $dst=memuh($src2+$src3<<#$offset)", + []>, + Requires<[HasV4T]>; + +// if (!Pv.new) Rd=memuh(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 45 in +def LDriuh_indexed_shl_cdnNotPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, + u2Imm:$offset), + "if (!$src1.new) $dst=memuh($src2+$src3<<#$offset)", + []>, + Requires<[HasV4T]>; + +// Rd=memh(Rt<<#u2+#U6) + +//// Load word. +// Rd=memw(Re=#U6) + +// Rd=memw(Rs+Rt<<#u2) +let AddedComplexity = 10, isPredicable = 1 in +def LDriw_indexed_V4 : LDInst<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2), + "$dst=memw($src1+$src2<<#0)", + [(set IntRegs:$dst, (load (add IntRegs:$src1, + IntRegs:$src2)))]>, + Requires<[HasV4T]>; + +// Rd=memw(Rs+Rt<<#u2) +let AddedComplexity = 40, isPredicable = 1 in +def LDriw_indexed_shl_V4 : LDInst<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$offset), + "$dst=memw($src1+$src2<<#$offset)", + [(set IntRegs:$dst, (load (add IntRegs:$src1, + (shl IntRegs:$src2, + u2ImmPred:$offset))))]>, + Requires<[HasV4T]>; + +//// Load word conditionally. +// if ([!]Pv[.new]) Rd=memw(Rs+Rt<<#u2) +// if (Pv) Rd=memw(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 15 in +def LDriw_indexed_cPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if ($src1) $dst=memw($src2+$src3<<#0)", + []>, + Requires<[HasV4T]>; + +// if (Pv.new) Rd=memh(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 15 in +def LDriw_indexed_cdnPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if ($src1.new) $dst=memw($src2+$src3<<#0)", + []>, + Requires<[HasV4T]>; + +// if (!Pv) Rd=memh(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 15 in +def LDriw_indexed_cNotPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if (!$src1) $dst=memw($src2+$src3<<#0)", + []>, + Requires<[HasV4T]>; + +// if (!Pv.new) Rd=memh(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 15 in +def LDriw_indexed_cdnNotPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "if (!$src1.new) $dst=memw($src2+$src3<<#0)", + []>, + Requires<[HasV4T]>; + +// if (Pv) Rd=memh(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 45 in +def LDriw_indexed_shl_cPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, + u2Imm:$offset), + "if ($src1) $dst=memw($src2+$src3<<#$offset)", + []>, + Requires<[HasV4T]>; + +// if (Pv.new) Rd=memh(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 45 in +def LDriw_indexed_shl_cdnPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, + u2Imm:$offset), + "if ($src1.new) $dst=memw($src2+$src3<<#$offset)", + []>, + Requires<[HasV4T]>; + +// if (!Pv) Rd=memh(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 45 in +def LDriw_indexed_shl_cNotPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, + u2Imm:$offset), + "if (!$src1) $dst=memw($src2+$src3<<#$offset)", + []>, + Requires<[HasV4T]>; + +// if (!Pv.new) Rd=memh(Rs+Rt<<#u2) +let mayLoad = 1, AddedComplexity = 45 in +def LDriw_indexed_shl_cdnNotPt_V4 : LDInst<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, + u2Imm:$offset), + "if (!$src1.new) $dst=memw($src2+$src3<<#$offset)", + []>, + Requires<[HasV4T]>; + +// Rd=memw(Rt<<#u2+#U6) + + +// Post-inc Load, Predicated, Dot new + + +let mayLoad = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in +def POST_LDrid_cdnPt_V4 : LDInstPI<(outs DoubleRegs:$dst1, IntRegs:$dst2), + (ins PredRegs:$src1, IntRegs:$src2, s4_3Imm:$src3), + "if ($src1.new) $dst1 = memd($src2++#$src3)", + [], + "$src2 = $dst2">, + Requires<[HasV4T]>; + +let mayLoad = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in +def POST_LDrid_cdnNotPt_V4 : LDInstPI<(outs DoubleRegs:$dst1, IntRegs:$dst2), + (ins PredRegs:$src1, IntRegs:$src2, s4_3Imm:$src3), + "if (!$src1.new) $dst1 = memd($src2++#$src3)", + [], + "$src2 = $dst2">, + Requires<[HasV4T]>; + +let mayLoad = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in +def POST_LDrib_cdnPt_V4 : LDInstPI<(outs IntRegs:$dst1, IntRegs:$dst2), + (ins PredRegs:$src1, IntRegs:$src2, s4_0Imm:$src3), + "if ($src1.new) $dst1 = memb($src2++#$src3)", + [], + "$src2 = $dst2">, + Requires<[HasV4T]>; + +let mayLoad = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in +def POST_LDrib_cdnNotPt_V4 : LDInstPI<(outs IntRegs:$dst1, IntRegs:$dst2), + (ins PredRegs:$src1, IntRegs:$src2, s4_0Imm:$src3), + "if (!$src1.new) $dst1 = memb($src2++#$src3)", + [], + "$src2 = $dst2">, + Requires<[HasV4T]>; + +let mayLoad = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in +def POST_LDrih_cdnPt_V4 : LDInstPI<(outs IntRegs:$dst1, IntRegs:$dst2), + (ins PredRegs:$src1, IntRegs:$src2, s4_1Imm:$src3), + "if ($src1.new) $dst1 = memh($src2++#$src3)", + [], + "$src2 = $dst2">, + Requires<[HasV4T]>; + +let mayLoad = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in +def POST_LDrih_cdnNotPt_V4 : LDInstPI<(outs IntRegs:$dst1, IntRegs:$dst2), + (ins PredRegs:$src1, IntRegs:$src2, s4_1Imm:$src3), + "if (!$src1.new) $dst1 = memh($src2++#$src3)", + [], + "$src2 = $dst2">, + Requires<[HasV4T]>; + +let mayLoad = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in +def POST_LDriub_cdnPt_V4 : LDInstPI<(outs IntRegs:$dst1, IntRegs:$dst2), + (ins PredRegs:$src1, IntRegs:$src2, s4_0Imm:$src3), + "if ($src1.new) $dst1 = memub($src2++#$src3)", + [], + "$src2 = $dst2">, + Requires<[HasV4T]>; + +let mayLoad = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in +def POST_LDriub_cdnNotPt_V4 : LDInstPI<(outs IntRegs:$dst1, IntRegs:$dst2), + (ins PredRegs:$src1, IntRegs:$src2, s4_0Imm:$src3), + "if (!$src1.new) $dst1 = memub($src2++#$src3)", + [], + "$src2 = $dst2">, + Requires<[HasV4T]>; + +let mayLoad = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in +def POST_LDriuh_cdnPt_V4 : LDInstPI<(outs IntRegs:$dst1, IntRegs:$dst2), + (ins PredRegs:$src1, IntRegs:$src2, s4_1Imm:$src3), + "if ($src1.new) $dst1 = memuh($src2++#$src3)", + [], + "$src2 = $dst2">, + Requires<[HasV4T]>; + +let mayLoad = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in +def POST_LDriuh_cdnNotPt_V4 : LDInstPI<(outs IntRegs:$dst1, IntRegs:$dst2), + (ins PredRegs:$src1, IntRegs:$src2, s4_1Imm:$src3), + "if (!$src1.new) $dst1 = memuh($src2++#$src3)", + [], + "$src2 = $dst2">, + Requires<[HasV4T]>; + +let mayLoad = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in +def POST_LDriw_cdnPt_V4 : LDInstPI<(outs IntRegs:$dst1, IntRegs:$dst2), + (ins PredRegs:$src1, IntRegs:$src2, s4_2Imm:$src3), + "if ($src1.new) $dst1 = memw($src2++#$src3)", + [], + "$src2 = $dst2">, + Requires<[HasV4T]>; + +let mayLoad = 1, hasCtrlDep = 1, neverHasSideEffects = 1 in +def POST_LDriw_cdnNotPt_V4 : LDInstPI<(outs IntRegs:$dst1, IntRegs:$dst2), + (ins PredRegs:$src1, IntRegs:$src2, s4_2Imm:$src3), + "if (!$src1.new) $dst1 = memw($src2++#$src3)", + [], + "$src2 = $dst2">, + Requires<[HasV4T]>; + + +//===----------------------------------------------------------------------===// +// LD - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// ST + +//===----------------------------------------------------------------------===// +/// +/// Assumptions::: ****** DO NOT IGNORE ******** +/// 1. Make sure that in post increment store, the zero'th operand is always the +/// post increment operand. +/// 2. Make sure that the store value operand(Rt/Rtt) in a store is always the +/// last operand. +/// + +// Store doubleword. +// memd(Re=#U6)=Rtt +// TODO: needs to be implemented + +// memd(Rs+#s11:3)=Rtt +// memd(Rs+Ru<<#u2)=Rtt +let AddedComplexity = 10, isPredicable = 1 in +def STrid_indexed_shl_V4 : STInst<(outs), + (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$src3, DoubleRegs:$src4), + "memd($src1+$src2<<#$src3) = $src4", + [(store DoubleRegs:$src4, (add IntRegs:$src1, + (shl IntRegs:$src2, u2ImmPred:$src3)))]>, + Requires<[HasV4T]>; + +// memd(Ru<<#u2+#U6)=Rtt +let AddedComplexity = 10 in +def STrid_shl_V4 : STInst<(outs), + (ins IntRegs:$src1, u2Imm:$src2, u6Imm:$src3, DoubleRegs:$src4), + "memd($src1<<#$src2+#$src3) = $src4", + [(store DoubleRegs:$src4, (shl IntRegs:$src1, + (add u2ImmPred:$src2, + u6ImmPred:$src3)))]>, + Requires<[HasV4T]>; + +// memd(Rx++#s4:3)=Rtt +// memd(Rx++#s4:3:circ(Mu))=Rtt +// memd(Rx++I:circ(Mu))=Rtt +// memd(Rx++Mu)=Rtt +// memd(Rx++Mu:brev)=Rtt +// memd(gp+#u16:3)=Rtt + +// Store doubleword conditionally. +// if ([!]Pv[.new]) memd(#u6)=Rtt +// TODO: needs to be implemented. + +// if ([!]Pv[.new]) memd(Rs+#u6:3)=Rtt +// if (Pv) memd(Rs+#u6:3)=Rtt +// if (Pv.new) memd(Rs+#u6:3)=Rtt +let AddedComplexity = 10, mayStore = 1, neverHasSideEffects = 1 in +def STrid_cdnPt_V4 : STInst<(outs), + (ins PredRegs:$src1, MEMri:$addr, DoubleRegs:$src2), + "if ($src1.new) memd($addr) = $src2", + []>, + Requires<[HasV4T]>; + +// if (!Pv) memd(Rs+#u6:3)=Rtt +// if (!Pv.new) memd(Rs+#u6:3)=Rtt +let AddedComplexity = 10, mayStore = 1, neverHasSideEffects = 1 in +def STrid_cdnNotPt_V4 : STInst<(outs), + (ins PredRegs:$src1, MEMri:$addr, DoubleRegs:$src2), + "if (!$src1.new) memd($addr) = $src2", + []>, + Requires<[HasV4T]>; + +// if (Pv) memd(Rs+#u6:3)=Rtt +// if (Pv.new) memd(Rs+#u6:3)=Rtt +let AddedComplexity = 10, mayStore = 1, neverHasSideEffects = 1 in +def STrid_indexed_cdnPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_3Imm:$src3, + DoubleRegs:$src4), + "if ($src1.new) memd($src2+#$src3) = $src4", + []>, + Requires<[HasV4T]>; + +// if (!Pv) memd(Rs+#u6:3)=Rtt +// if (!Pv.new) memd(Rs+#u6:3)=Rtt +let AddedComplexity = 10, mayStore = 1, neverHasSideEffects = 1 in +def STrid_indexed_cdnNotPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_3Imm:$src3, + DoubleRegs:$src4), + "if (!$src1.new) memd($src2+#$src3) = $src4", + []>, + Requires<[HasV4T]>; + +// if ([!]Pv[.new]) memd(Rs+Ru<<#u2)=Rtt +// if (Pv) memd(Rs+Ru<<#u2)=Rtt +let AddedComplexity = 10, mayStore = 1, neverHasSideEffects = 1 in +def STrid_indexed_shl_cPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, + DoubleRegs:$src5), + "if ($src1) memd($src2+$src3<<#$src4) = $src5", + []>, + Requires<[HasV4T]>; + +// if (Pv.new) memd(Rs+Ru<<#u2)=Rtt +let AddedComplexity = 10, mayStore = 1, neverHasSideEffects = 1 in +def STrid_indexed_shl_cdnPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, + DoubleRegs:$src5), + "if ($src1) memd($src2+$src3<<#$src4) = $src5", + []>, + Requires<[HasV4T]>; +// if (!Pv) memd(Rs+Ru<<#u2)=Rtt +let AddedComplexity = 10, mayStore = 1, neverHasSideEffects = 1 in +def STrid_indexed_shl_cNotPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, + DoubleRegs:$src5), + "if (!$src1) memd($src2+$src3<<#$src4) = $src5", + []>, + Requires<[HasV4T]>; +// if (!Pv.new) memd(Rs+Ru<<#u2)=Rtt +let AddedComplexity = 10, mayStore = 1, neverHasSideEffects = 1 in +def STrid_indexed_shl_cdnNotPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, + DoubleRegs:$src5), + "if (!$src1.new) memd($src2+$src3<<#$src4) = $src5", + []>, + Requires<[HasV4T]>; + +// if ([!]Pv[.new]) memd(Rx++#s4:3)=Rtt +// if (Pv) memd(Rx++#s4:3)=Rtt +// if (Pv.new) memd(Rx++#s4:3)=Rtt +let AddedComplexity = 10, mayStore = 1, neverHasSideEffects = 1 in +def POST_STdri_cdnPt_V4 : STInstPI<(outs IntRegs:$dst), + (ins PredRegs:$src1, DoubleRegs:$src2, IntRegs:$src3, + s4_3Imm:$offset), + "if ($src1.new) memd($src3++#$offset) = $src2", + [], + "$src3 = $dst">, + Requires<[HasV4T]>; + +// if (!Pv) memd(Rx++#s4:3)=Rtt +// if (!Pv.new) memd(Rx++#s4:3)=Rtt +let AddedComplexity = 10, mayStore = 1, neverHasSideEffects = 1 in +def POST_STdri_cdnNotPt_V4 : STInstPI<(outs IntRegs:$dst), + (ins PredRegs:$src1, DoubleRegs:$src2, IntRegs:$src3, + s4_3Imm:$offset), + "if (!$src1.new) memd($src3++#$offset) = $src2", + [], + "$src3 = $dst">, + Requires<[HasV4T]>; + + +// Store byte. +// memb(Re=#U6)=Rt +// TODO: needs to be implemented. +// memb(Rs+#s11:0)=Rt +// memb(Rs+#u6:0)=#S8 +let AddedComplexity = 10, isPredicable = 1 in +def STrib_imm_V4 : STInst<(outs), + (ins IntRegs:$src1, u6_0Imm:$src2, s8Imm:$src3), + "memb($src1+#$src2) = #$src3", + [(truncstorei8 s8ImmPred:$src3, (add IntRegs:$src1, + u6_0ImmPred:$src2))]>, + Requires<[HasV4T]>; + +// memb(Rs+Ru<<#u2)=Rt +let AddedComplexity = 10, isPredicable = 1 in +def STrib_indexed_shl_V4 : STInst<(outs), + (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$src3, IntRegs:$src4), + "memb($src1+$src2<<#$src3) = $src4", + [(truncstorei8 IntRegs:$src4, (add IntRegs:$src1, + (shl IntRegs:$src2, + u2ImmPred:$src3)))]>, + Requires<[HasV4T]>; + +// memb(Ru<<#u2+#U6)=Rt +let AddedComplexity = 10 in +def STrib_shl_V4 : STInst<(outs), + (ins IntRegs:$src1, u2Imm:$src2, u6Imm:$src3, IntRegs:$src4), + "memb($src1<<#$src2+#$src3) = $src4", + [(truncstorei8 IntRegs:$src4, (shl IntRegs:$src1, + (add u2ImmPred:$src2, + u6ImmPred:$src3)))]>, + Requires<[HasV4T]>; + +// memb(Rx++#s4:0:circ(Mu))=Rt +// memb(Rx++I:circ(Mu))=Rt +// memb(Rx++Mu)=Rt +// memb(Rx++Mu:brev)=Rt +// memb(gp+#u16:0)=Rt + + +// Store byte conditionally. +// if ([!]Pv[.new]) memb(#u6)=Rt +// if ([!]Pv[.new]) memb(Rs+#u6:0)=#S6 +// if (Pv) memb(Rs+#u6:0)=#S6 +let mayStore = 1, neverHasSideEffects = 1 in +def STrib_imm_cPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3, s6Imm:$src4), + "if ($src1) memb($src2+#$src3) = #$src4", + []>, + Requires<[HasV4T]>; + +// if (Pv.new) memb(Rs+#u6:0)=#S6 +let mayStore = 1, neverHasSideEffects = 1 in +def STrib_imm_cdnPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3, s6Imm:$src4), + "if ($src1.new) memb($src2+#$src3) = #$src4", + []>, + Requires<[HasV4T]>; + +// if (!Pv) memb(Rs+#u6:0)=#S6 +let mayStore = 1, neverHasSideEffects = 1 in +def STrib_imm_cNotPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3, s6Imm:$src4), + "if (!$src1) memb($src2+#$src3) = #$src4", + []>, + Requires<[HasV4T]>; + +// if (!Pv.new) memb(Rs+#u6:0)=#S6 +let mayStore = 1, neverHasSideEffects = 1 in +def STrib_imm_cdnNotPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3, s6Imm:$src4), + "if (!$src1.new) memb($src2+#$src3) = #$src4", + []>, + Requires<[HasV4T]>; + +// if ([!]Pv[.new]) memb(Rs+#u6:0)=Rt +// if (Pv) memb(Rs+#u6:0)=Rt +// if (Pv.new) memb(Rs+#u6:0)=Rt +let mayStore = 1, neverHasSideEffects = 1 in +def STrib_cdnPt_V4 : STInst<(outs), + (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), + "if ($src1.new) memb($addr) = $src2", + []>, + Requires<[HasV4T]>; + +// if (!Pv) memb(Rs+#u6:0)=Rt +// if (!Pv.new) memb(Rs+#u6:0)=Rt +let mayStore = 1, neverHasSideEffects = 1 in +def STrib_cdnNotPt_V4 : STInst<(outs), + (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), + "if (!$src1.new) memb($addr) = $src2", + []>, + Requires<[HasV4T]>; + +// if (Pv) memb(Rs+#u6:0)=Rt +// if (!Pv) memb(Rs+#u6:0)=Rt +// if (Pv.new) memb(Rs+#u6:0)=Rt +let mayStore = 1, neverHasSideEffects = 1 in +def STrib_indexed_cdnPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3, IntRegs:$src4), + "if ($src1.new) memb($src2+#$src3) = $src4", + []>, + Requires<[HasV4T]>; + +// if (!Pv.new) memb(Rs+#u6:0)=Rt +let mayStore = 1, neverHasSideEffects = 1 in +def STrib_indexed_cdnNotPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3, IntRegs:$src4), + "if (!$src1.new) memb($src2+#$src3) = $src4", + []>, + Requires<[HasV4T]>; + +// if ([!]Pv[.new]) memb(Rs+Ru<<#u2)=Rt +// if (Pv) memb(Rs+Ru<<#u2)=Rt +let mayStore = 1, AddedComplexity = 10 in +def STrib_indexed_shl_cPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, + IntRegs:$src5), + "if ($src1) memb($src2+$src3<<#$src4) = $src5", + []>, + Requires<[HasV4T]>; + +// if (Pv.new) memb(Rs+Ru<<#u2)=Rt +let mayStore = 1, AddedComplexity = 10 in +def STrib_indexed_shl_cdnPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, + IntRegs:$src5), + "if ($src1.new) memb($src2+$src3<<#$src4) = $src5", + []>, + Requires<[HasV4T]>; + +// if (!Pv) memb(Rs+Ru<<#u2)=Rt +let mayStore = 1, AddedComplexity = 10 in +def STrib_indexed_shl_cNotPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, + IntRegs:$src5), + "if (!$src1) memb($src2+$src3<<#$src4) = $src5", + []>, + Requires<[HasV4T]>; + +// if (!Pv.new) memb(Rs+Ru<<#u2)=Rt +let mayStore = 1, AddedComplexity = 10 in +def STrib_indexed_shl_cdnNotPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, + IntRegs:$src5), + "if (!$src1.new) memb($src2+$src3<<#$src4) = $src5", + []>, + Requires<[HasV4T]>; + +// if ([!]Pv[.new]) memb(Rx++#s4:0)=Rt +// if (Pv) memb(Rx++#s4:0)=Rt +// if (Pv.new) memb(Rx++#s4:0)=Rt +let mayStore = 1, hasCtrlDep = 1 in +def POST_STbri_cdnPt_V4 : STInstPI<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_0Imm:$offset), + "if ($src1.new) memb($src3++#$offset) = $src2", + [],"$src3 = $dst">, + Requires<[HasV4T]>; + +// if (!Pv) memb(Rx++#s4:0)=Rt +// if (!Pv.new) memb(Rx++#s4:0)=Rt +let mayStore = 1, hasCtrlDep = 1 in +def POST_STbri_cdnNotPt_V4 : STInstPI<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_0Imm:$offset), + "if (!$src1.new) memb($src3++#$offset) = $src2", + [],"$src3 = $dst">, + Requires<[HasV4T]>; + + +// Store halfword. +// memh(Re=#U6)=Rt.H +// TODO: needs to be implemented + +// memh(Re=#U6)=Rt +// TODO: needs to be implemented + +// memh(Rs+#s11:1)=Rt.H +// memh(Rs+#s11:1)=Rt +// memh(Rs+#u6:1)=#S8 +let AddedComplexity = 10, isPredicable = 1 in +def STrih_imm_V4 : STInst<(outs), + (ins IntRegs:$src1, u6_1Imm:$src2, s8Imm:$src3), + "memh($src1+#$src2) = #$src3", + [(truncstorei16 s8ImmPred:$src3, (add IntRegs:$src1, + u6_1ImmPred:$src2))]>, + Requires<[HasV4T]>; + +// memh(Rs+Ru<<#u2)=Rt.H +// TODO: needs to be implemented. + +// memh(Rs+Ru<<#u2)=Rt +let AddedComplexity = 10, isPredicable = 1 in +def STrih_indexed_shl_V4 : STInst<(outs), + (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$src3, IntRegs:$src4), + "memh($src1+$src2<<#$src3) = $src4", + [(truncstorei16 IntRegs:$src4, (add IntRegs:$src1, + (shl IntRegs:$src2, + u2ImmPred:$src3)))]>, + Requires<[HasV4T]>; + +// memh(Ru<<#u2+#U6)=Rt.H +// memh(Ru<<#u2+#U6)=Rt +let AddedComplexity = 10 in +def STrih_shl_V4 : STInst<(outs), + (ins IntRegs:$src1, u2Imm:$src2, u6Imm:$src3, IntRegs:$src4), + "memh($src1<<#$src2+#$src3) = $src4", + [(truncstorei16 IntRegs:$src4, (shl IntRegs:$src1, + (add u2ImmPred:$src2, + u6ImmPred:$src3)))]>, + Requires<[HasV4T]>; + +// memh(Rx++#s4:1:circ(Mu))=Rt.H +// memh(Rx++#s4:1:circ(Mu))=Rt +// memh(Rx++I:circ(Mu))=Rt.H +// memh(Rx++I:circ(Mu))=Rt +// memh(Rx++Mu)=Rt.H +// memh(Rx++Mu)=Rt +// memh(Rx++Mu:brev)=Rt.H +// memh(Rx++Mu:brev)=Rt +// memh(gp+#u16:1)=Rt.H +// memh(gp+#u16:1)=Rt + + +// Store halfword conditionally. +// if ([!]Pv[.new]) memh(#u6)=Rt.H +// if ([!]Pv[.new]) memh(#u6)=Rt + +// if ([!]Pv[.new]) memh(Rs+#u6:1)=#S6 +// if (Pv) memh(Rs+#u6:1)=#S6 +let mayStore = 1, neverHasSideEffects = 1 in +def STrih_imm_cPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3, s6Imm:$src4), + "if ($src1) memh($src2+#$src3) = #$src4", + []>, + Requires<[HasV4T]>; + +// if (Pv.new) memh(Rs+#u6:1)=#S6 +let mayStore = 1, neverHasSideEffects = 1 in +def STrih_imm_cdnPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3, s6Imm:$src4), + "if ($src1.new) memh($src2+#$src3) = #$src4", + []>, + Requires<[HasV4T]>; + +// if (!Pv) memh(Rs+#u6:1)=#S6 +let mayStore = 1, neverHasSideEffects = 1 in +def STrih_imm_cNotPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3, s6Imm:$src4), + "if (!$src1) memh($src2+#$src3) = #$src4", + []>, + Requires<[HasV4T]>; + +// if (!Pv.new) memh(Rs+#u6:1)=#S6 +let mayStore = 1, neverHasSideEffects = 1 in +def STrih_imm_cdnNotPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3, s6Imm:$src4), + "if (!$src1.new) memh($src2+#$src3) = #$src4", + []>, + Requires<[HasV4T]>; + +// if ([!]Pv[.new]) memh(Rs+#u6:1)=Rt.H +// TODO: needs to be implemented. + +// if ([!]Pv[.new]) memh(Rs+#u6:1)=Rt +// if (Pv) memh(Rs+#u6:1)=Rt +// if (Pv.new) memh(Rs+#u6:1)=Rt +let mayStore = 1, neverHasSideEffects = 1 in +def STrih_cdnPt_V4 : STInst<(outs), + (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), + "if ($src1.new) memh($addr) = $src2", + []>, + Requires<[HasV4T]>; + +// if (!Pv) memh(Rs+#u6:1)=Rt +// if (!Pv.new) memh(Rs+#u6:1)=Rt +let mayStore = 1, neverHasSideEffects = 1 in +def STrih_cdnNotPt_V4 : STInst<(outs), + (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), + "if (!$src1.new) memh($addr) = $src2", + []>, + Requires<[HasV4T]>; + +// if (Pv.new) memh(Rs+#u6:1)=Rt +let mayStore = 1, neverHasSideEffects = 1 in +def STrih_indexed_cdnPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3, IntRegs:$src4), + "if ($src1.new) memh($src2+#$src3) = $src4", + []>, + Requires<[HasV4T]>; + +// if (!Pv.new) memh(Rs+#u6:1)=Rt +let mayStore = 1, neverHasSideEffects = 1 in +def STrih_indexed_cdnNotPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3, IntRegs:$src4), + "if (!$src1.new) memh($src2+#$src3) = $src4", + []>, + Requires<[HasV4T]>; + +// if ([!]Pv[.new]) memh(Rs+Ru<<#u2)=Rt.H +// if ([!]Pv[.new]) memh(Rs+Ru<<#u2)=Rt +// if (Pv) memh(Rs+Ru<<#u2)=Rt +let mayStore = 1, AddedComplexity = 10 in +def STrih_indexed_shl_cPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, + IntRegs:$src5), + "if ($src1) memh($src2+$src3<<#$src4) = $src5", + []>, + Requires<[HasV4T]>; + +// if (Pv.new) memh(Rs+Ru<<#u2)=Rt +def STrih_indexed_shl_cdnPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, + IntRegs:$src5), + "if ($src1.new) memh($src2+$src3<<#$src4) = $src5", + []>, + Requires<[HasV4T]>; + +// if (!Pv) memh(Rs+Ru<<#u2)=Rt +let mayStore = 1, AddedComplexity = 10 in +def STrih_indexed_shl_cNotPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, + IntRegs:$src5), + "if (!$src1) memh($src2+$src3<<#$src4) = $src5", + []>, + Requires<[HasV4T]>; + +// if (!Pv.new) memh(Rs+Ru<<#u2)=Rt +let mayStore = 1, AddedComplexity = 10 in +def STrih_indexed_shl_cdnNotPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, + IntRegs:$src5), + "if (!$src1.new) memh($src2+$src3<<#$src4) = $src5", + []>, + Requires<[HasV4T]>; + +// if ([!]Pv[.new]) memh(Rx++#s4:1)=Rt.H +// TODO: Needs to be implemented. + +// if ([!]Pv[.new]) memh(Rx++#s4:1)=Rt +// if (Pv) memh(Rx++#s4:1)=Rt +// if (Pv.new) memh(Rx++#s4:1)=Rt +let mayStore = 1, hasCtrlDep = 1 in +def POST_SThri_cdnPt_V4 : STInstPI<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_1Imm:$offset), + "if ($src1.new) memh($src3++#$offset) = $src2", + [],"$src3 = $dst">, + Requires<[HasV4T]>; + +// if (!Pv) memh(Rx++#s4:1)=Rt +// if (!Pv.new) memh(Rx++#s4:1)=Rt +let mayStore = 1, hasCtrlDep = 1 in +def POST_SThri_cdnNotPt_V4 : STInstPI<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_1Imm:$offset), + "if (!$src1.new) memh($src3++#$offset) = $src2", + [],"$src3 = $dst">, + Requires<[HasV4T]>; + + +// Store word. +// memw(Re=#U6)=Rt +// TODO: Needs to be implemented. + +// memw(Rs+#s11:2)=Rt +// memw(Rs+#u6:2)=#S8 +let AddedComplexity = 10, isPredicable = 1 in +def STriw_imm_V4 : STInst<(outs), + (ins IntRegs:$src1, u6_2Imm:$src2, s8Imm:$src3), + "memw($src1+#$src2) = #$src3", + [(store s8ImmPred:$src3, (add IntRegs:$src1, u6_2ImmPred:$src2))]>, + Requires<[HasV4T]>; + +// memw(Rs+Ru<<#u2)=Rt +let AddedComplexity = 10, isPredicable = 1 in +def STriw_indexed_shl_V4 : STInst<(outs), + (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$src3, IntRegs:$src4), + "memw($src1+$src2<<#$src3) = $src4", + [(store IntRegs:$src4, (add IntRegs:$src1, + (shl IntRegs:$src2, u2ImmPred:$src3)))]>, + Requires<[HasV4T]>; + +// memw(Ru<<#u2+#U6)=Rt +let AddedComplexity = 10 in +def STriw_shl_V4 : STInst<(outs), + (ins IntRegs:$src1, u2Imm:$src2, u6Imm:$src3, IntRegs:$src4), + "memw($src1<<#$src2+#$src3) = $src4", + [(store IntRegs:$src4, (shl IntRegs:$src1, + (add u2ImmPred:$src2, u6ImmPred:$src3)))]>, + Requires<[HasV4T]>; + +// memw(Rx++#s4:2)=Rt +// memw(Rx++#s4:2:circ(Mu))=Rt +// memw(Rx++I:circ(Mu))=Rt +// memw(Rx++Mu)=Rt +// memw(Rx++Mu:brev)=Rt +// memw(gp+#u16:2)=Rt + + +// Store word conditionally. +// if ([!]Pv[.new]) memw(#u6)=Rt +// TODO: Needs to be implemented. + +// if ([!]Pv[.new]) memw(Rs+#u6:2)=#S6 +// if (Pv) memw(Rs+#u6:2)=#S6 +let mayStore = 1, neverHasSideEffects = 1 in +def STriw_imm_cPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3, s6Imm:$src4), + "if ($src1) memw($src2+#$src3) = #$src4", + []>, + Requires<[HasV4T]>; + +// if (Pv.new) memw(Rs+#u6:2)=#S6 +let mayStore = 1, neverHasSideEffects = 1 in +def STriw_imm_cdnPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3, s6Imm:$src4), + "if ($src1.new) memw($src2+#$src3) = #$src4", + []>, + Requires<[HasV4T]>; + +// if (!Pv) memw(Rs+#u6:2)=#S6 +let mayStore = 1, neverHasSideEffects = 1 in +def STriw_imm_cNotPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3, s6Imm:$src4), + "if (!$src1) memw($src2+#$src3) = #$src4", + []>, + Requires<[HasV4T]>; + +// if (!Pv.new) memw(Rs+#u6:2)=#S6 +let mayStore = 1, neverHasSideEffects = 1 in +def STriw_imm_cdnNotPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3, s6Imm:$src4), + "if (!$src1.new) memw($src2+#$src3) = #$src4", + []>, + Requires<[HasV4T]>; + +// if ([!]Pv[.new]) memw(Rs+#u6:2)=Rt +// if (Pv) memw(Rs+#u6:2)=Rt +// if (Pv.new) memw(Rs+#u6:2)=Rt +let mayStore = 1, neverHasSideEffects = 1 in +def STriw_cdnPt_V4 : STInst<(outs), + (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), + "if ($src1.new) memw($addr) = $src2", + []>, + Requires<[HasV4T]>; + +// if (!Pv) memw(Rs+#u6:2)=Rt +// if (!Pv.new) memw(Rs+#u6:2)=Rt +let mayStore = 1, neverHasSideEffects = 1 in +def STriw_cdnNotPt_V4 : STInst<(outs), + (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), + "if (!$src1.new) memw($addr) = $src2", + []>, + Requires<[HasV4T]>; + +// if (Pv) memw(Rs+#u6:2)=Rt +// if (!Pv) memw(Rs+#u6:2)=Rt +// if (Pv.new) memw(Rs+#u6:2)=Rt +let mayStore = 1, neverHasSideEffects = 1 in +def STriw_indexed_cdnPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3, IntRegs:$src4), + "if ($src1.new) memw($src2+#$src3) = $src4", + []>, + Requires<[HasV4T]>; + +// if (!Pv.new) memw(Rs+#u6:2)=Rt +let mayStore = 1, neverHasSideEffects = 1 in +def STriw_indexed_cdnNotPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3, IntRegs:$src4), + "if (!$src1.new) memw($src2+#$src3) = $src4", + []>, + Requires<[HasV4T]>; + +// if ([!]Pv[.new]) memw(Rs+Ru<<#u2)=Rt +// if (Pv) memw(Rs+Ru<<#u2)=Rt +let mayStore = 1, AddedComplexity = 10 in +def STriw_indexed_shl_cPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, + IntRegs:$src5), + "if ($src1) memw($src2+$src3<<#$src4) = $src5", + []>, + Requires<[HasV4T]>; + +// if (Pv.new) memw(Rs+Ru<<#u2)=Rt +let mayStore = 1, AddedComplexity = 10 in +def STriw_indexed_shl_cdnPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, + IntRegs:$src5), + "if ($src1.new) memw($src2+$src3<<#$src4) = $src5", + []>, + Requires<[HasV4T]>; + +// if (!Pv) memw(Rs+Ru<<#u2)=Rt +let mayStore = 1, AddedComplexity = 10 in +def STriw_indexed_shl_cNotPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, + IntRegs:$src5), + "if (!$src1) memw($src2+$src3<<#$src4) = $src5", + []>, + Requires<[HasV4T]>; + +// if (!Pv.new) memw(Rs+Ru<<#u2)=Rt +let mayStore = 1, AddedComplexity = 10 in +def STriw_indexed_shl_cdnNotPt_V4 : STInst<(outs), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, + IntRegs:$src5), + "if (!$src1.new) memw($src2+$src3<<#$src4) = $src5", + []>, + Requires<[HasV4T]>; + +// if ([!]Pv[.new]) memw(Rx++#s4:2)=Rt +// if (Pv) memw(Rx++#s4:2)=Rt +// if (Pv.new) memw(Rx++#s4:2)=Rt +let mayStore = 1, hasCtrlDep = 1 in +def POST_STwri_cdnPt_V4 : STInstPI<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_2Imm:$offset), + "if ($src1.new) memw($src3++#$offset) = $src2", + [],"$src3 = $dst">, + Requires<[HasV4T]>; + +// if (!Pv) memw(Rx++#s4:2)=Rt +// if (!Pv.new) memw(Rx++#s4:2)=Rt +let mayStore = 1, hasCtrlDep = 1 in +def POST_STwri_cdnNotPt_V4 : STInstPI<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_2Imm:$offset), + "if (!$src1.new) memw($src3++#$offset) = $src2", + [],"$src3 = $dst">, + Requires<[HasV4T]>; + + +//===----------------------------------------------------------------------=== +// ST - +//===----------------------------------------------------------------------=== + + +//===----------------------------------------------------------------------===// +// NV/ST + +//===----------------------------------------------------------------------===// + +// Store new-value byte. + +// memb(Re=#U6)=Nt.new +// memb(Rs+#s11:0)=Nt.new +let mayStore = 1, isPredicable = 1 in +def STrib_nv_V4 : NVInst_V4<(outs), (ins MEMri:$addr, IntRegs:$src1), + "memb($addr) = $src1.new", + []>, + Requires<[HasV4T]>; + +let mayStore = 1, isPredicable = 1 in +def STrib_indexed_nv_V4 : NVInst_V4<(outs), + (ins IntRegs:$src1, s11_0Imm:$src2, IntRegs:$src3), + "memb($src1+#$src2) = $src3.new", + []>, + Requires<[HasV4T]>; + +// memb(Rs+Ru<<#u2)=Nt.new +let mayStore = 1, AddedComplexity = 10, isPredicable = 1 in +def STrib_indexed_shl_nv_V4 : NVInst_V4<(outs), + (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$src3, IntRegs:$src4), + "memb($src1+$src2<<#$src3) = $src4.new", + []>, + Requires<[HasV4T]>; + +// memb(Ru<<#u2+#U6)=Nt.new +let mayStore = 1, AddedComplexity = 10 in +def STrib_shl_nv_V4 : NVInst_V4<(outs), + (ins IntRegs:$src1, u2Imm:$src2, u6Imm:$src3, IntRegs:$src4), + "memb($src1<<#$src2+#$src3) = $src4.new", + []>, + Requires<[HasV4T]>; + +// memb(Rx++#s4:0)=Nt.new +let mayStore = 1, hasCtrlDep = 1, isPredicable = 1 in +def POST_STbri_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2, s4_0Imm:$offset), + "memb($src2++#$offset) = $src1.new", + [], + "$src2 = $dst">, + Requires<[HasV4T]>; + +// memb(Rx++#s4:0:circ(Mu))=Nt.new +// memb(Rx++I:circ(Mu))=Nt.new +// memb(Rx++Mu)=Nt.new +// memb(Rx++Mu:brev)=Nt.new + +// memb(gp+#u16:0)=Nt.new +let mayStore = 1, neverHasSideEffects = 1 in +def STrib_GP_nv_V4 : NVInst_V4<(outs), + (ins globaladdress:$global, u16Imm:$offset, IntRegs:$src), + "memb(#$global+$offset) = $src.new", + []>, + Requires<[HasV4T]>; + + +// Store new-value byte conditionally. +// if ([!]Pv[.new]) memb(#u6)=Nt.new +// if (Pv) memb(Rs+#u6:0)=Nt.new +let mayStore = 1, neverHasSideEffects = 1 in +def STrib_cPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), + "if ($src1) memb($addr) = $src2.new", + []>, + Requires<[HasV4T]>; + +// if (Pv.new) memb(Rs+#u6:0)=Nt.new +let mayStore = 1, neverHasSideEffects = 1 in +def STrib_cdnPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), + "if ($src1.new) memb($addr) = $src2.new", + []>, + Requires<[HasV4T]>; + +// if (!Pv) memb(Rs+#u6:0)=Nt.new +let mayStore = 1, neverHasSideEffects = 1 in +def STrib_cNotPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), + "if (!$src1) memb($addr) = $src2.new", + []>, + Requires<[HasV4T]>; + +// if (!Pv.new) memb(Rs+#u6:0)=Nt.new +let mayStore = 1, neverHasSideEffects = 1 in +def STrib_cdnNotPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), + "if (!$src1.new) memb($addr) = $src2.new", + []>, + Requires<[HasV4T]>; + +// if (Pv) memb(Rs+#u6:0)=Nt.new +let mayStore = 1, neverHasSideEffects = 1 in +def STrib_indexed_cPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3, IntRegs:$src4), + "if ($src1) memb($src2+#$src3) = $src4.new", + []>, + Requires<[HasV4T]>; + +// if (Pv.new) memb(Rs+#u6:0)=Nt.new +let mayStore = 1, neverHasSideEffects = 1 in +def STrib_indexed_cdnPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3, IntRegs:$src4), + "if ($src1.new) memb($src2+#$src3) = $src4.new", + []>, + Requires<[HasV4T]>; + +// if (!Pv) memb(Rs+#u6:0)=Nt.new +let mayStore = 1, neverHasSideEffects = 1 in +def STrib_indexed_cNotPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3, IntRegs:$src4), + "if (!$src1) memb($src2+#$src3) = $src4.new", + []>, + Requires<[HasV4T]>; + +// if (!Pv.new) memb(Rs+#u6:0)=Nt.new +let mayStore = 1, neverHasSideEffects = 1 in +def STrib_indexed_cdnNotPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_0Imm:$src3, IntRegs:$src4), + "if (!$src1.new) memb($src2+#$src3) = $src4.new", + []>, + Requires<[HasV4T]>; + + +// if ([!]Pv[.new]) memb(Rs+Ru<<#u2)=Nt.new +// if (Pv) memb(Rs+Ru<<#u2)=Nt.new +let mayStore = 1, AddedComplexity = 10 in +def STrib_indexed_shl_cPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, + IntRegs:$src5), + "if ($src1) memb($src2+$src3<<#$src4) = $src5.new", + []>, + Requires<[HasV4T]>; + +// if (Pv.new) memb(Rs+Ru<<#u2)=Nt.new +let mayStore = 1, AddedComplexity = 10 in +def STrib_indexed_shl_cdnPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, + IntRegs:$src5), + "if ($src1.new) memb($src2+$src3<<#$src4) = $src5.new", + []>, + Requires<[HasV4T]>; + +// if (!Pv) memb(Rs+Ru<<#u2)=Nt.new +let mayStore = 1, AddedComplexity = 10 in +def STrib_indexed_shl_cNotPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, + IntRegs:$src5), + "if (!$src1) memb($src2+$src3<<#$src4) = $src5.new", + []>, + Requires<[HasV4T]>; + +// if (!Pv.new) memb(Rs+Ru<<#u2)=Nt.new +let mayStore = 1, AddedComplexity = 10 in +def STrib_indexed_shl_cdnNotPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, + IntRegs:$src5), + "if (!$src1.new) memb($src2+$src3<<#$src4) = $src5.new", + []>, + Requires<[HasV4T]>; + +// if ([!]Pv[.new]) memb(Rx++#s4:0)=Nt.new +// if (Pv) memb(Rx++#s4:0)=Nt.new +let mayStore = 1, hasCtrlDep = 1 in +def POST_STbri_cPt_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_0Imm:$offset), + "if ($src1) memb($src3++#$offset) = $src2.new", + [],"$src3 = $dst">, + Requires<[HasV4T]>; + +// if (Pv.new) memb(Rx++#s4:0)=Nt.new +let mayStore = 1, hasCtrlDep = 1 in +def POST_STbri_cdnPt_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_0Imm:$offset), + "if ($src1.new) memb($src3++#$offset) = $src2.new", + [],"$src3 = $dst">, + Requires<[HasV4T]>; + +// if (!Pv) memb(Rx++#s4:0)=Nt.new +let mayStore = 1, hasCtrlDep = 1 in +def POST_STbri_cNotPt_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_0Imm:$offset), + "if (!$src1) memb($src3++#$offset) = $src2.new", + [],"$src3 = $dst">, + Requires<[HasV4T]>; + +// if (!Pv.new) memb(Rx++#s4:0)=Nt.new +let mayStore = 1, hasCtrlDep = 1 in +def POST_STbri_cdnNotPt_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_0Imm:$offset), + "if (!$src1.new) memb($src3++#$offset) = $src2.new", + [],"$src3 = $dst">, + Requires<[HasV4T]>; + + +// Store new-value halfword. +// memh(Re=#U6)=Nt.new +// memh(Rs+#s11:1)=Nt.new +let mayStore = 1, isPredicable = 1 in +def STrih_nv_V4 : NVInst_V4<(outs), (ins MEMri:$addr, IntRegs:$src1), + "memh($addr) = $src1.new", + []>, + Requires<[HasV4T]>; + +let mayStore = 1, isPredicable = 1 in +def STrih_indexed_nv_V4 : NVInst_V4<(outs), + (ins IntRegs:$src1, s11_1Imm:$src2, IntRegs:$src3), + "memh($src1+#$src2) = $src3.new", + []>, + Requires<[HasV4T]>; + +// memh(Rs+Ru<<#u2)=Nt.new +let mayStore = 1, AddedComplexity = 10, isPredicable = 1 in +def STrih_indexed_shl_nv_V4 : NVInst_V4<(outs), + (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$src3, IntRegs:$src4), + "memh($src1+$src2<<#$src3) = $src4.new", + []>, + Requires<[HasV4T]>; + +// memh(Ru<<#u2+#U6)=Nt.new +let mayStore = 1, AddedComplexity = 10 in +def STrih_shl_nv_V4 : NVInst_V4<(outs), + (ins IntRegs:$src1, u2Imm:$src2, u6Imm:$src3, IntRegs:$src4), + "memh($src1<<#$src2+#$src3) = $src4.new", + []>, + Requires<[HasV4T]>; + +// memh(Rx++#s4:1)=Nt.new +let mayStore = 1, hasCtrlDep = 1, isPredicable = 1 in +def POST_SThri_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2, s4_1Imm:$offset), + "memh($src2++#$offset) = $src1.new", + [], + "$src2 = $dst">, + Requires<[HasV4T]>; + +// memh(Rx++#s4:1:circ(Mu))=Nt.new +// memh(Rx++I:circ(Mu))=Nt.new +// memh(Rx++Mu)=Nt.new +// memh(Rx++Mu:brev)=Nt.new + +// memh(gp+#u16:1)=Nt.new +let mayStore = 1, neverHasSideEffects = 1 in +def STrih_GP_nv_V4 : NVInst_V4<(outs), + (ins globaladdress:$global, u16Imm:$offset, IntRegs:$src), + "memh(#$global+$offset) = $src.new", + []>, + Requires<[HasV4T]>; + + +// Store new-value halfword conditionally. + +// if ([!]Pv[.new]) memh(#u6)=Nt.new + +// if ([!]Pv[.new]) memh(Rs+#u6:1)=Nt.new +// if (Pv) memh(Rs+#u6:1)=Nt.new +let mayStore = 1, neverHasSideEffects = 1 in +def STrih_cPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), + "if ($src1) memh($addr) = $src2.new", + []>, + Requires<[HasV4T]>; + +// if (Pv.new) memh(Rs+#u6:1)=Nt.new +let mayStore = 1, neverHasSideEffects = 1 in +def STrih_cdnPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), + "if ($src1.new) memh($addr) = $src2.new", + []>, + Requires<[HasV4T]>; + +// if (!Pv) memh(Rs+#u6:1)=Nt.new +let mayStore = 1, neverHasSideEffects = 1 in +def STrih_cNotPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), + "if (!$src1) memh($addr) = $src2.new", + []>, + Requires<[HasV4T]>; + +// if (!Pv.new) memh(Rs+#u6:1)=Nt.new +let mayStore = 1, neverHasSideEffects = 1 in +def STrih_cdnNotPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), + "if (!$src1.new) memh($addr) = $src2.new", + []>, + Requires<[HasV4T]>; + +// if (Pv) memh(Rs+#u6:1)=Nt.new +let mayStore = 1, neverHasSideEffects = 1 in +def STrih_indexed_cPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3, IntRegs:$src4), + "if ($src1) memh($src2+#$src3) = $src4.new", + []>, + Requires<[HasV4T]>; + +// if (Pv.new) memh(Rs+#u6:1)=Nt.new +let mayStore = 1, neverHasSideEffects = 1 in +def STrih_indexed_cdnPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3, IntRegs:$src4), + "if ($src1.new) memh($src2+#$src3) = $src4.new", + []>, + Requires<[HasV4T]>; + +// if (!Pv) memh(Rs+#u6:1)=Nt.new +let mayStore = 1, neverHasSideEffects = 1 in +def STrih_indexed_cNotPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3, IntRegs:$src4), + "if (!$src1) memh($src2+#$src3) = $src4.new", + []>, + Requires<[HasV4T]>; + +// if (!Pv.new) memh(Rs+#u6:1)=Nt.new +let mayStore = 1, neverHasSideEffects = 1 in +def STrih_indexed_cdnNotPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_1Imm:$src3, IntRegs:$src4), + "if (!$src1.new) memh($src2+#$src3) = $src4.new", + []>, + Requires<[HasV4T]>; + +// if ([!]Pv[.new]) memh(Rs+Ru<<#u2)=Nt.new +// if (Pv) memh(Rs+Ru<<#u2)=Nt.new +let mayStore = 1, AddedComplexity = 10 in +def STrih_indexed_shl_cPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, + IntRegs:$src5), + "if ($src1) memh($src2+$src3<<#$src4) = $src5.new", + []>, + Requires<[HasV4T]>; + +// if (Pv.new) memh(Rs+Ru<<#u2)=Nt.new +let mayStore = 1, AddedComplexity = 10 in +def STrih_indexed_shl_cdnPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, + IntRegs:$src5), + "if ($src1.new) memh($src2+$src3<<#$src4) = $src5.new", + []>, + Requires<[HasV4T]>; + +// if (!Pv) memh(Rs+Ru<<#u2)=Nt.new +let mayStore = 1, AddedComplexity = 10 in +def STrih_indexed_shl_cNotPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, + IntRegs:$src5), + "if (!$src1) memh($src2+$src3<<#$src4) = $src5.new", + []>, + Requires<[HasV4T]>; + +// if (!Pv.new) memh(Rs+Ru<<#u2)=Nt.new +let mayStore = 1, AddedComplexity = 10 in +def STrih_indexed_shl_cdnNotPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, + IntRegs:$src5), + "if (!$src1.new) memh($src2+$src3<<#$src4) = $src5.new", + []>, + Requires<[HasV4T]>; + +// if ([!]Pv[]) memh(Rx++#s4:1)=Nt.new +// if (Pv) memh(Rx++#s4:1)=Nt.new +let mayStore = 1, hasCtrlDep = 1 in +def POST_SThri_cPt_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_1Imm:$offset), + "if ($src1) memh($src3++#$offset) = $src2.new", + [],"$src3 = $dst">, + Requires<[HasV4T]>; + +// if (Pv.new) memh(Rx++#s4:1)=Nt.new +let mayStore = 1, hasCtrlDep = 1 in +def POST_SThri_cdnPt_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_1Imm:$offset), + "if ($src1.new) memh($src3++#$offset) = $src2.new", + [],"$src3 = $dst">, + Requires<[HasV4T]>; + +// if (!Pv) memh(Rx++#s4:1)=Nt.new +let mayStore = 1, hasCtrlDep = 1 in +def POST_SThri_cNotPt_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_1Imm:$offset), + "if (!$src1) memh($src3++#$offset) = $src2.new", + [],"$src3 = $dst">, + Requires<[HasV4T]>; + +// if (!Pv.new) memh(Rx++#s4:1)=Nt.new +let mayStore = 1, hasCtrlDep = 1 in +def POST_SThri_cdnNotPt_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_1Imm:$offset), + "if (!$src1.new) memh($src3++#$offset) = $src2.new", + [],"$src3 = $dst">, + Requires<[HasV4T]>; + + +// Store new-value word. + +// memw(Re=#U6)=Nt.new +// memw(Rs+#s11:2)=Nt.new +let mayStore = 1, isPredicable = 1 in +def STriw_nv_V4 : NVInst_V4<(outs), + (ins MEMri:$addr, IntRegs:$src1), + "memw($addr) = $src1.new", + []>, + Requires<[HasV4T]>; + +let mayStore = 1, isPredicable = 1 in +def STriw_indexed_nv_V4 : NVInst_V4<(outs), + (ins IntRegs:$src1, s11_2Imm:$src2, IntRegs:$src3), + "memw($src1+#$src2) = $src3.new", + []>, + Requires<[HasV4T]>; + +// memw(Rs+Ru<<#u2)=Nt.new +let mayStore = 1, AddedComplexity = 10, isPredicable = 1 in +def STriw_indexed_shl_nv_V4 : NVInst_V4<(outs), + (ins IntRegs:$src1, IntRegs:$src2, u2Imm:$src3, IntRegs:$src4), + "memw($src1+$src2<<#$src3) = $src4.new", + []>, + Requires<[HasV4T]>; + +// memw(Ru<<#u2+#U6)=Nt.new +let mayStore = 1, AddedComplexity = 10 in +def STriw_shl_nv_V4 : NVInst_V4<(outs), + (ins IntRegs:$src1, u2Imm:$src2, u6Imm:$src3, IntRegs:$src4), + "memw($src1<<#$src2+#$src3) = $src4.new", + []>, + Requires<[HasV4T]>; + +// memw(Rx++#s4:2)=Nt.new +let mayStore = 1, hasCtrlDep = 1, isPredicable = 1 in +def POST_STwri_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2, s4_2Imm:$offset), + "memw($src2++#$offset) = $src1.new", + [], + "$src2 = $dst">, + Requires<[HasV4T]>; + +// memw(Rx++#s4:2:circ(Mu))=Nt.new +// memw(Rx++I:circ(Mu))=Nt.new +// memw(Rx++Mu)=Nt.new +// memw(Rx++Mu:brev)=Nt.new +// memw(gp+#u16:2)=Nt.new +let mayStore = 1, neverHasSideEffects = 1 in +def STriw_GP_nv_V4 : NVInst_V4<(outs), + (ins globaladdress:$global, u16Imm:$offset, IntRegs:$src), + "memw(#$global+$offset) = $src.new", + []>, + Requires<[HasV4T]>; + + +// Store new-value word conditionally. + +// if ([!]Pv[.new]) memw(#u6)=Nt.new + +// if ([!]Pv[.new]) memw(Rs+#u6:2)=Nt.new +// if (Pv) memw(Rs+#u6:2)=Nt.new +let mayStore = 1, neverHasSideEffects = 1 in +def STriw_cPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), + "if ($src1) memw($addr) = $src2.new", + []>, + Requires<[HasV4T]>; + +// if (Pv.new) memw(Rs+#u6:2)=Nt.new +let mayStore = 1, neverHasSideEffects = 1 in +def STriw_cdnPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), + "if ($src1.new) memw($addr) = $src2.new", + []>, + Requires<[HasV4T]>; + +// if (!Pv) memw(Rs+#u6:2)=Nt.new +let mayStore = 1, neverHasSideEffects = 1 in +def STriw_cNotPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), + "if (!$src1) memw($addr) = $src2.new", + []>, + Requires<[HasV4T]>; + +// if (!Pv.new) memw(Rs+#u6:2)=Nt.new +let mayStore = 1, neverHasSideEffects = 1 in +def STriw_cdnNotPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, MEMri:$addr, IntRegs:$src2), + "if (!$src1.new) memw($addr) = $src2.new", + []>, + Requires<[HasV4T]>; + +// if (Pv) memw(Rs+#u6:2)=Nt.new +let mayStore = 1, neverHasSideEffects = 1 in +def STriw_indexed_cPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3, IntRegs:$src4), + "if ($src1) memw($src2+#$src3) = $src4.new", + []>, + Requires<[HasV4T]>; + +// if (Pv.new) memw(Rs+#u6:2)=Nt.new +let mayStore = 1, neverHasSideEffects = 1 in +def STriw_indexed_cdnPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3, IntRegs:$src4), + "if ($src1.new) memw($src2+#$src3) = $src4.new", + []>, + Requires<[HasV4T]>; + +// if (!Pv) memw(Rs+#u6:2)=Nt.new +let mayStore = 1, neverHasSideEffects = 1 in +def STriw_indexed_cNotPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3, IntRegs:$src4), + "if (!$src1) memw($src2+#$src3) = $src4.new", + []>, + Requires<[HasV4T]>; + +// if (!Pv.new) memw(Rs+#u6:2)=Nt.new +let mayStore = 1, neverHasSideEffects = 1 in +def STriw_indexed_cdnNotPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, IntRegs:$src2, u6_2Imm:$src3, IntRegs:$src4), + "if (!$src1.new) memw($src2+#$src3) = $src4.new", + []>, + Requires<[HasV4T]>; + + +// if ([!]Pv[.new]) memw(Rs+Ru<<#u2)=Nt.new +// if (Pv) memw(Rs+Ru<<#u2)=Nt.new +let mayStore = 1, AddedComplexity = 10 in +def STriw_indexed_shl_cPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, + IntRegs:$src5), + "if ($src1) memw($src2+$src3<<#$src4) = $src5.new", + []>, + Requires<[HasV4T]>; + +// if (Pv.new) memw(Rs+Ru<<#u2)=Nt.new +let mayStore = 1, AddedComplexity = 10 in +def STriw_indexed_shl_cdnPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, + IntRegs:$src5), + "if ($src1.new) memw($src2+$src3<<#$src4) = $src5.new", + []>, + Requires<[HasV4T]>; + +// if (!Pv) memw(Rs+Ru<<#u2)=Nt.new +let mayStore = 1, AddedComplexity = 10 in +def STriw_indexed_shl_cNotPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, + IntRegs:$src5), + "if (!$src1) memw($src2+$src3<<#$src4) = $src5.new", + []>, + Requires<[HasV4T]>; + +// if (!Pv.new) memw(Rs+Ru<<#u2)=Nt.new +let mayStore = 1, AddedComplexity = 10 in +def STriw_indexed_shl_cdnNotPt_nv_V4 : NVInst_V4<(outs), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, u2Imm:$src4, + IntRegs:$src5), + "if (!$src1.new) memw($src2+$src3<<#$src4) = $src5.new", + []>, + Requires<[HasV4T]>; + +// if ([!]Pv[.new]) memw(Rx++#s4:2)=Nt.new +// if (Pv) memw(Rx++#s4:2)=Nt.new +let mayStore = 1, hasCtrlDep = 1 in +def POST_STwri_cPt_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_2Imm:$offset), + "if ($src1) memw($src3++#$offset) = $src2.new", + [],"$src3 = $dst">, + Requires<[HasV4T]>; + +// if (Pv.new) memw(Rx++#s4:2)=Nt.new +let mayStore = 1, hasCtrlDep = 1 in +def POST_STwri_cdnPt_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_2Imm:$offset), + "if ($src1.new) memw($src3++#$offset) = $src2.new", + [],"$src3 = $dst">, + Requires<[HasV4T]>; + +// if (!Pv) memw(Rx++#s4:2)=Nt.new +let mayStore = 1, hasCtrlDep = 1 in +def POST_STwri_cNotPt_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_2Imm:$offset), + "if (!$src1) memw($src3++#$offset) = $src2.new", + [],"$src3 = $dst">, + Requires<[HasV4T]>; + +// if (!Pv.new) memw(Rx++#s4:2)=Nt.new +let mayStore = 1, hasCtrlDep = 1 in +def POST_STwri_cdnNotPt_nv_V4 : NVInstPI_V4<(outs IntRegs:$dst), + (ins PredRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4_2Imm:$offset), + "if (!$src1.new) memw($src3++#$offset) = $src2.new", + [],"$src3 = $dst">, + Requires<[HasV4T]>; + + +//===----------------------------------------------------------------------===// +// NV/ST - +//===----------------------------------------------------------------------===// + + +//===----------------------------------------------------------------------===// +// XTYPE/ALU + +//===----------------------------------------------------------------------===// + +// Add and accumulate. +// Rd=add(Rs,add(Ru,#s6)) +def ADDr_ADDri_V4 : MInst<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2, s6Imm:$src3), + "$dst = add($src1, add($src2, #$src3))", + [(set IntRegs:$dst, + (add IntRegs:$src1, (add IntRegs:$src2, s6ImmPred:$src3)))]>, + Requires<[HasV4T]>; + +// Rd=add(Rs,sub(#s6,Ru)) +def ADDr_SUBri_V4 : MInst<(outs IntRegs:$dst), + (ins IntRegs:$src1, s6Imm:$src2, IntRegs:$src3), + "$dst = add($src1, sub(#$src2, $src3))", + [(set IntRegs:$dst, + (add IntRegs:$src1, (sub s6ImmPred:$src2, IntRegs:$src3)))]>, + Requires<[HasV4T]>; + +// Generates the same instruction as ADDr_SUBri_V4 but matches different +// pattern. +// Rd=add(Rs,sub(#s6,Ru)) +def ADDri_SUBr_V4 : MInst<(outs IntRegs:$dst), + (ins IntRegs:$src1, s6Imm:$src2, IntRegs:$src3), + "$dst = add($src1, sub(#$src2, $src3))", + [(set IntRegs:$dst, + (sub (add IntRegs:$src1, s6ImmPred:$src2), IntRegs:$src3))]>, + Requires<[HasV4T]>; + + +// Add or subtract doublewords with carry. +//TODO: +// Rdd=add(Rss,Rtt,Px):carry +//TODO: +// Rdd=sub(Rss,Rtt,Px):carry + + +// Logical doublewords. +// Rdd=and(Rtt,~Rss) +def ANDd_NOTd_V4 : MInst<(outs DoubleRegs:$dst), + (ins DoubleRegs:$src1, DoubleRegs:$src2), + "$dst = and($src1, ~$src2)", + [(set DoubleRegs:$dst, (and DoubleRegs:$src1, + (not DoubleRegs:$src2)))]>, + Requires<[HasV4T]>; + +// Rdd=or(Rtt,~Rss) +def ORd_NOTd_V4 : MInst<(outs DoubleRegs:$dst), + (ins DoubleRegs:$src1, DoubleRegs:$src2), + "$dst = or($src1, ~$src2)", + [(set DoubleRegs:$dst, + (or DoubleRegs:$src1, (not DoubleRegs:$src2)))]>, + Requires<[HasV4T]>; + + +// Logical-logical doublewords. +// Rxx^=xor(Rss,Rtt) +def XORd_XORdd: MInst_acc<(outs DoubleRegs:$dst), + (ins DoubleRegs:$src1, DoubleRegs:$src2, DoubleRegs:$src3), + "$dst ^= xor($src2, $src3)", + [(set DoubleRegs:$dst, + (xor DoubleRegs:$src1, (xor DoubleRegs:$src2, DoubleRegs:$src3)))], + "$src1 = $dst">, + Requires<[HasV4T]>; + + +// Logical-logical words. +// Rx=or(Ru,and(Rx,#s10)) +def ORr_ANDri_V4 : MInst_acc<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs: $src2, s10Imm:$src3), + "$dst = or($src1, and($src2, #$src3))", + [(set IntRegs:$dst, + (or IntRegs:$src1, (and IntRegs:$src2, s10ImmPred:$src3)))], + "$src2 = $dst">, + Requires<[HasV4T]>; + +// Rx[&|^]=and(Rs,Rt) +// Rx&=and(Rs,Rt) +def ANDr_ANDrr_V4 : MInst_acc<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), + "$dst &= and($src2, $src3)", + [(set IntRegs:$dst, + (and IntRegs:$src1, (and IntRegs:$src2, IntRegs:$src3)))], + "$src1 = $dst">, + Requires<[HasV4T]>; + +// Rx|=and(Rs,Rt) +def ORr_ANDrr_V4 : MInst_acc<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), + "$dst |= and($src2, $src3)", + [(set IntRegs:$dst, + (or IntRegs:$src1, (and IntRegs:$src2, IntRegs:$src3)))], + "$src1 = $dst">, + Requires<[HasV4T]>; + +// Rx^=and(Rs,Rt) +def XORr_ANDrr_V4 : MInst_acc<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), + "$dst ^= and($src2, $src3)", + [(set IntRegs:$dst, + (xor IntRegs:$src1, (and IntRegs:$src2, IntRegs:$src3)))], + "$src1 = $dst">, + Requires<[HasV4T]>; + +// Rx[&|^]=and(Rs,~Rt) +// Rx&=and(Rs,~Rt) +def ANDr_ANDr_NOTr_V4 : MInst_acc<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), + "$dst &= and($src2, ~$src3)", + [(set IntRegs:$dst, + (and IntRegs:$src1, (and IntRegs:$src2, (not IntRegs:$src3))))], + "$src1 = $dst">, + Requires<[HasV4T]>; + +// Rx|=and(Rs,~Rt) +def ORr_ANDr_NOTr_V4 : MInst_acc<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), + "$dst |= and($src2, ~$src3)", + [(set IntRegs:$dst, + (or IntRegs:$src1, (and IntRegs:$src2, (not IntRegs:$src3))))], + "$src1 = $dst">, + Requires<[HasV4T]>; + +// Rx^=and(Rs,~Rt) +def XORr_ANDr_NOTr_V4 : MInst_acc<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), + "$dst ^= and($src2, ~$src3)", + [(set IntRegs:$dst, + (xor IntRegs:$src1, (and IntRegs:$src2, (not IntRegs:$src3))))], + "$src1 = $dst">, + Requires<[HasV4T]>; + +// Rx[&|^]=or(Rs,Rt) +// Rx&=or(Rs,Rt) +def ANDr_ORrr_V4 : MInst_acc<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), + "$dst &= or($src2, $src3)", + [(set IntRegs:$dst, + (and IntRegs:$src1, (or IntRegs:$src2, IntRegs:$src3)))], + "$src1 = $dst">, + Requires<[HasV4T]>; + +// Rx|=or(Rs,Rt) +def ORr_ORrr_V4 : MInst_acc<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), + "$dst |= or($src2, $src3)", + [(set IntRegs:$dst, + (or IntRegs:$src1, (or IntRegs:$src2, IntRegs:$src3)))], + "$src1 = $dst">, + Requires<[HasV4T]>; + +// Rx^=or(Rs,Rt) +def XORr_ORrr_V4 : MInst_acc<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), + "$dst ^= or($src2, $src3)", + [(set IntRegs:$dst, + (xor IntRegs:$src1, (or IntRegs:$src2, IntRegs:$src3)))], + "$src1 = $dst">, + Requires<[HasV4T]>; + +// Rx[&|^]=xor(Rs,Rt) +// Rx&=xor(Rs,Rt) +def ANDr_XORrr_V4 : MInst_acc<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), + "$dst &= xor($src2, $src3)", + [(set IntRegs:$dst, + (and IntRegs:$src1, (xor IntRegs:$src2, IntRegs:$src3)))], + "$src1 = $dst">, + Requires<[HasV4T]>; + +// Rx|=xor(Rs,Rt) +def ORr_XORrr_V4 : MInst_acc<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), + "$dst |= xor($src2, $src3)", + [(set IntRegs:$dst, + (and IntRegs:$src1, (xor IntRegs:$src2, IntRegs:$src3)))], + "$src1 = $dst">, + Requires<[HasV4T]>; + +// Rx^=xor(Rs,Rt) +def XORr_XORrr_V4 : MInst_acc<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs: $src2, IntRegs:$src3), + "$dst ^= xor($src2, $src3)", + [(set IntRegs:$dst, + (and IntRegs:$src1, (xor IntRegs:$src2, IntRegs:$src3)))], + "$src1 = $dst">, + Requires<[HasV4T]>; + +// Rx|=and(Rs,#s10) +def ORr_ANDri2_V4 : MInst_acc<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs: $src2, s10Imm:$src3), + "$dst |= and($src2, #$src3)", + [(set IntRegs:$dst, + (or IntRegs:$src1, (and IntRegs:$src2, s10ImmPred:$src3)))], + "$src1 = $dst">, + Requires<[HasV4T]>; + +// Rx|=or(Rs,#s10) +def ORr_ORri_V4 : MInst_acc<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs: $src2, s10Imm:$src3), + "$dst |= or($src2, #$src3)", + [(set IntRegs:$dst, + (or IntRegs:$src1, (and IntRegs:$src2, s10ImmPred:$src3)))], + "$src1 = $dst">, + Requires<[HasV4T]>; + + +// Modulo wrap +// Rd=modwrap(Rs,Rt) +// Round +// Rd=cround(Rs,#u5) +// Rd=cround(Rs,Rt) +// Rd=round(Rs,#u5)[:sat] +// Rd=round(Rs,Rt)[:sat] +// Vector reduce add unsigned halfwords +// Rd=vraddh(Rss,Rtt) +// Vector add bytes +// Rdd=vaddb(Rss,Rtt) +// Vector conditional negate +// Rdd=vcnegh(Rss,Rt) +// Rxx+=vrcnegh(Rss,Rt) +// Vector maximum bytes +// Rdd=vmaxb(Rtt,Rss) +// Vector reduce maximum halfwords +// Rxx=vrmaxh(Rss,Ru) +// Rxx=vrmaxuh(Rss,Ru) +// Vector reduce maximum words +// Rxx=vrmaxuw(Rss,Ru) +// Rxx=vrmaxw(Rss,Ru) +// Vector minimum bytes +// Rdd=vminb(Rtt,Rss) +// Vector reduce minimum halfwords +// Rxx=vrminh(Rss,Ru) +// Rxx=vrminuh(Rss,Ru) +// Vector reduce minimum words +// Rxx=vrminuw(Rss,Ru) +// Rxx=vrminw(Rss,Ru) +// Vector subtract bytes +// Rdd=vsubb(Rss,Rtt) + +//===----------------------------------------------------------------------===// +// XTYPE/ALU - +//===----------------------------------------------------------------------===// + + +//===----------------------------------------------------------------------===// +// XTYPE/MPY + +//===----------------------------------------------------------------------===// + +// Multiply and user lower result. +// Rd=add(#u6,mpyi(Rs,#U6)) +def ADDi_MPYri_V4 : MInst<(outs IntRegs:$dst), + (ins u6Imm:$src1, IntRegs:$src2, u6Imm:$src3), + "$dst = add(#$src1, mpyi($src2, #$src3))", + [(set IntRegs:$dst, + (add (mul IntRegs:$src2, u6ImmPred:$src3), u6ImmPred:$src1))]>, + Requires<[HasV4T]>; + +// Rd=add(#u6,mpyi(Rs,Rt)) + +def ADDi_MPYrr_V4 : MInst<(outs IntRegs:$dst), + (ins u6Imm:$src1, IntRegs:$src2, IntRegs:$src3), + "$dst = add(#$src1, mpyi($src2, $src3))", + [(set IntRegs:$dst, + (add (mul IntRegs:$src2, IntRegs:$src3), u6ImmPred:$src1))]>, + Requires<[HasV4T]>; + +// Rd=add(Ru,mpyi(#u6:2,Rs)) +def ADDr_MPYir_V4 : MInst<(outs IntRegs:$dst), + (ins IntRegs:$src1, u6Imm:$src2, IntRegs:$src3), + "$dst = add($src1, mpyi(#$src2, $src3))", + [(set IntRegs:$dst, + (add IntRegs:$src1, (mul IntRegs:$src3, u6_2ImmPred:$src2)))]>, + Requires<[HasV4T]>; + +// Rd=add(Ru,mpyi(Rs,#u6)) +def ADDr_MPYri_V4 : MInst<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2, u6Imm:$src3), + "$dst = add($src1, mpyi($src2, #$src3))", + [(set IntRegs:$dst, + (add IntRegs:$src1, (mul IntRegs:$src2, u6ImmPred:$src3)))]>, + Requires<[HasV4T]>; + +// Rx=add(Ru,mpyi(Rx,Rs)) +def ADDr_MPYrr_V4 : MInst_acc<(outs IntRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2, IntRegs:$src3), + "$dst = add($src1, mpyi($src2, $src3))", + [(set IntRegs:$dst, + (add IntRegs:$src1, (mul IntRegs:$src2, IntRegs:$src3)))], + "$src2 = $dst">, + Requires<[HasV4T]>; + + +// Polynomial multiply words +// Rdd=pmpyw(Rs,Rt) +// Rxx^=pmpyw(Rs,Rt) + +// Vector reduce multiply word by signed half (32x16) +// Rdd=vrmpyweh(Rss,Rtt)[:<<1] +// Rdd=vrmpywoh(Rss,Rtt)[:<<1] +// Rxx+=vrmpyweh(Rss,Rtt)[:<<1] +// Rxx+=vrmpywoh(Rss,Rtt)[:<<1] + +// Multiply and use upper result +// Rd=mpy(Rs,Rt.H):<<1:sat +// Rd=mpy(Rs,Rt.L):<<1:sat +// Rd=mpy(Rs,Rt):<<1 +// Rd=mpy(Rs,Rt):<<1:sat +// Rd=mpysu(Rs,Rt) +// Rx+=mpy(Rs,Rt):<<1:sat +// Rx-=mpy(Rs,Rt):<<1:sat + +// Vector multiply bytes +// Rdd=vmpybsu(Rs,Rt) +// Rdd=vmpybu(Rs,Rt) +// Rxx+=vmpybsu(Rs,Rt) +// Rxx+=vmpybu(Rs,Rt) + +// Vector polynomial multiply halfwords +// Rdd=vpmpyh(Rs,Rt) +// Rxx^=vpmpyh(Rs,Rt) + +//===----------------------------------------------------------------------===// +// XTYPE/MPY - +//===----------------------------------------------------------------------===// + + +//===----------------------------------------------------------------------===// +// XTYPE/SHIFT + +//===----------------------------------------------------------------------===// + +// Shift by immediate and accumulate. +// Rx=add(#u8,asl(Rx,#U5)) +def ADDi_ASLri_V4 : MInst_acc<(outs IntRegs:$dst), + (ins u8Imm:$src1, IntRegs:$src2, u5Imm:$src3), + "$dst = add(#$src1, asl($src2, #$src3))", + [(set IntRegs:$dst, + (add (shl IntRegs:$src2, u5ImmPred:$src3), u8ImmPred:$src1))], + "$src2 = $dst">, + Requires<[HasV4T]>; + +// Rx=add(#u8,lsr(Rx,#U5)) +def ADDi_LSRri_V4 : MInst_acc<(outs IntRegs:$dst), + (ins u8Imm:$src1, IntRegs:$src2, u5Imm:$src3), + "$dst = add(#$src1, lsr($src2, #$src3))", + [(set IntRegs:$dst, + (add (srl IntRegs:$src2, u5ImmPred:$src3), u8ImmPred:$src1))], + "$src2 = $dst">, + Requires<[HasV4T]>; + +// Rx=sub(#u8,asl(Rx,#U5)) +def SUBi_ASLri_V4 : MInst_acc<(outs IntRegs:$dst), + (ins u8Imm:$src1, IntRegs:$src2, u5Imm:$src3), + "$dst = sub(#$src1, asl($src2, #$src3))", + [(set IntRegs:$dst, + (sub (shl IntRegs:$src2, u5ImmPred:$src3), u8ImmPred:$src1))], + "$src2 = $dst">, + Requires<[HasV4T]>; + +// Rx=sub(#u8,lsr(Rx,#U5)) +def SUBi_LSRri_V4 : MInst_acc<(outs IntRegs:$dst), + (ins u8Imm:$src1, IntRegs:$src2, u5Imm:$src3), + "$dst = sub(#$src1, lsr($src2, #$src3))", + [(set IntRegs:$dst, + (sub (srl IntRegs:$src2, u5ImmPred:$src3), u8ImmPred:$src1))], + "$src2 = $dst">, + Requires<[HasV4T]>; + + +//Shift by immediate and logical. +//Rx=and(#u8,asl(Rx,#U5)) +def ANDi_ASLri_V4 : MInst_acc<(outs IntRegs:$dst), + (ins u8Imm:$src1, IntRegs:$src2, u5Imm:$src3), + "$dst = and(#$src1, asl($src2, #$src3))", + [(set IntRegs:$dst, + (and (shl IntRegs:$src2, u5ImmPred:$src3), u8ImmPred:$src1))], + "$src2 = $dst">, + Requires<[HasV4T]>; + +//Rx=and(#u8,lsr(Rx,#U5)) +def ANDi_LSRri_V4 : MInst_acc<(outs IntRegs:$dst), + (ins u8Imm:$src1, IntRegs:$src2, u5Imm:$src3), + "$dst = and(#$src1, lsr($src2, #$src3))", + [(set IntRegs:$dst, + (and (srl IntRegs:$src2, u5ImmPred:$src3), u8ImmPred:$src1))], + "$src2 = $dst">, + Requires<[HasV4T]>; + +//Rx=or(#u8,asl(Rx,#U5)) +def ORi_ASLri_V4 : MInst_acc<(outs IntRegs:$dst), + (ins u8Imm:$src1, IntRegs:$src2, u5Imm:$src3), + "$dst = or(#$src1, asl($src2, #$src3))", + [(set IntRegs:$dst, + (or (shl IntRegs:$src2, u5ImmPred:$src3), u8ImmPred:$src1))], + "$src2 = $dst">, + Requires<[HasV4T]>; + +//Rx=or(#u8,lsr(Rx,#U5)) +def ORi_LSRri_V4 : MInst_acc<(outs IntRegs:$dst), + (ins u8Imm:$src1, IntRegs:$src2, u5Imm:$src3), + "$dst = or(#$src1, lsr($src2, #$src3))", + [(set IntRegs:$dst, + (or (srl IntRegs:$src2, u5ImmPred:$src3), u8ImmPred:$src1))], + "$src2 = $dst">, + Requires<[HasV4T]>; + + +//Shift by register. +//Rd=lsl(#s6,Rt) +def LSLi_V4 : MInst<(outs IntRegs:$dst), (ins s6Imm:$src1, IntRegs:$src2), + "$dst = lsl(#$src1, $src2)", + [(set IntRegs:$dst, (shl s6ImmPred:$src1, IntRegs:$src2))]>, + Requires<[HasV4T]>; + + +//Shift by register and logical. +//Rxx^=asl(Rss,Rt) +def ASLd_rr_xor_V4 : MInst_acc<(outs DoubleRegs:$dst), + (ins DoubleRegs:$src1, DoubleRegs:$src2, IntRegs:$src3), + "$dst ^= asl($src2, $src3)", + [(set DoubleRegs:$dst, + (xor DoubleRegs:$src1, (shl DoubleRegs:$src2, IntRegs:$src3)))], + "$src1 = $dst">, + Requires<[HasV4T]>; + +//Rxx^=asr(Rss,Rt) +def ASRd_rr_xor_V4 : MInst_acc<(outs DoubleRegs:$dst), + (ins DoubleRegs:$src1, DoubleRegs:$src2, IntRegs:$src3), + "$dst ^= asr($src2, $src3)", + [(set DoubleRegs:$dst, + (xor DoubleRegs:$src1, (sra DoubleRegs:$src2, IntRegs:$src3)))], + "$src1 = $dst">, + Requires<[HasV4T]>; + +//Rxx^=lsl(Rss,Rt) +def LSLd_rr_xor_V4 : MInst_acc<(outs DoubleRegs:$dst), + (ins DoubleRegs:$src1, DoubleRegs:$src2, IntRegs:$src3), + "$dst ^= lsl($src2, $src3)", + [(set DoubleRegs:$dst, + (xor DoubleRegs:$src1, (shl DoubleRegs:$src2, IntRegs:$src3)))], + "$src1 = $dst">, + Requires<[HasV4T]>; + +//Rxx^=lsr(Rss,Rt) +def LSRd_rr_xor_V4 : MInst_acc<(outs DoubleRegs:$dst), + (ins DoubleRegs:$src1, DoubleRegs:$src2, IntRegs:$src3), + "$dst ^= lsr($src2, $src3)", + [(set DoubleRegs:$dst, + (xor DoubleRegs:$src1, (srl DoubleRegs:$src2, IntRegs:$src3)))], + "$src1 = $dst">, + Requires<[HasV4T]>; + + +//===----------------------------------------------------------------------===// +// XTYPE/SHIFT - +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// MEMOP: Word, Half, Byte +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// MEMOP: Word +// +// Implemented: +// MEMw_ADDi_indexed_V4 : memw(Rs+#u6:2)+=#U5 +// MEMw_SUBi_indexed_V4 : memw(Rs+#u6:2)-=#U5 +// MEMw_ADDr_indexed_V4 : memw(Rs+#u6:2)+=Rt +// MEMw_SUBr_indexed_V4 : memw(Rs+#u6:2)-=Rt +// MEMw_CLRr_indexed_V4 : memw(Rs+#u6:2)&=Rt +// MEMw_SETr_indexed_V4 : memw(Rs+#u6:2)|=Rt +// MEMw_ADDi_V4 : memw(Rs+#u6:2)+=#U5 +// MEMw_SUBi_V4 : memw(Rs+#u6:2)-=#U5 +// MEMw_ADDr_V4 : memw(Rs+#u6:2)+=Rt +// MEMw_SUBr_V4 : memw(Rs+#u6:2)-=Rt +// MEMw_CLRr_V4 : memw(Rs+#u6:2)&=Rt +// MEMw_SETr_V4 : memw(Rs+#u6:2)|=Rt +// +// Not implemented: +// MEMw_CLRi_indexed_V4 : memw(Rs+#u6:2)=clrbit(#U5) +// MEMw_SETi_indexed_V4 : memw(Rs+#u6:2)=setbit(#U5) +// MEMw_CLRi_V4 : memw(Rs+#u6:2)=clrbit(#U5) +// MEMw_SETi_V4 : memw(Rs+#u6:2)=setbit(#U5) +//===----------------------------------------------------------------------===// + + +// MEMw_ADDSUBi_indexed_V4: +// pseudo operation for MEMw_ADDi_indexed_V4 and +// MEMw_SUBi_indexed_V4 a later pass will change it +// to the corresponding pattern. +let AddedComplexity = 30 in +def MEMw_ADDSUBi_indexed_MEM_V4 : MEMInst_V4<(outs), + (ins IntRegs:$base, u6_2Imm:$offset, m6Imm:$addend), + "Error; should not emit", + [(store (add (load (add IntRegs:$base, u6_2ImmPred:$offset)), +m6ImmPred:$addend), + (add IntRegs:$base, u6_2ImmPred:$offset))]>, + Requires<[HasV4T, UseMEMOP]>; + +// memw(Rs+#u6:2) += #U5 +let AddedComplexity = 30 in +def MEMw_ADDi_indexed_MEM_V4 : MEMInst_V4<(outs), + (ins IntRegs:$base, u6_2Imm:$offset, u5Imm:$addend), + "memw($base+#$offset) += $addend", + []>, + Requires<[HasV4T, UseMEMOP]>; + +// memw(Rs+#u6:2) -= #U5 +let AddedComplexity = 30 in +def MEMw_SUBi_indexed_MEM_V4 : MEMInst_V4<(outs), + (ins IntRegs:$base, u6_2Imm:$offset, u5Imm:$subend), + "memw($base+#$offset) -= $subend", + []>, + Requires<[HasV4T, UseMEMOP]>; + +// memw(Rs+#u6:2) += Rt +let AddedComplexity = 30 in +def MEMw_ADDr_indexed_MEM_V4 : MEMInst_V4<(outs), + (ins IntRegs:$base, u6_2Imm:$offset, IntRegs:$addend), + "memw($base+#$offset) += $addend", + [(store (add (load (add IntRegs:$base, u6_2ImmPred:$offset)), +IntRegs:$addend), + (add IntRegs:$base, u6_2ImmPred:$offset))]>, + Requires<[HasV4T, UseMEMOP]>; + +// memw(Rs+#u6:2) -= Rt +let AddedComplexity = 30 in +def MEMw_SUBr_indexed_MEM_V4 : MEMInst_V4<(outs), + (ins IntRegs:$base, u6_2Imm:$offset, IntRegs:$subend), + "memw($base+#$offset) -= $subend", + [(store (sub (load (add IntRegs:$base, u6_2ImmPred:$offset)), +IntRegs:$subend), + (add IntRegs:$base, u6_2ImmPred:$offset))]>, + Requires<[HasV4T, UseMEMOP]>; + +// memw(Rs+#u6:2) &= Rt +let AddedComplexity = 30 in +def MEMw_ANDr_indexed_MEM_V4 : MEMInst_V4<(outs), + (ins IntRegs:$base, u6_2Imm:$offset, IntRegs:$andend), + "memw($base+#$offset) += $andend", + [(store (and (load (add IntRegs:$base, u6_2ImmPred:$offset)), +IntRegs:$andend), + (add IntRegs:$base, u6_2ImmPred:$offset))]>, + Requires<[HasV4T, UseMEMOP]>; + +// memw(Rs+#u6:2) |= Rt +let AddedComplexity = 30 in +def MEMw_ORr_indexed_MEM_V4 : MEMInst_V4<(outs), + (ins IntRegs:$base, u6_2Imm:$offset, IntRegs:$orend), + "memw($base+#$offset) |= $orend", + [(store (or (load (add IntRegs:$base, u6_2ImmPred:$offset)), + IntRegs:$orend), + (add IntRegs:$base, u6_2ImmPred:$offset))]>, + Requires<[HasV4T, UseMEMOP]>; + +// MEMw_ADDSUBi_V4: +// Pseudo operation for MEMw_ADDi_V4 and MEMw_SUBi_V4 +// a later pass will change it to the right pattern. +let AddedComplexity = 30 in +def MEMw_ADDSUBi_MEM_V4 : MEMInst_V4<(outs), + (ins MEMri:$addr, m6Imm:$addend), + "Error; should not emit", + [(store (add (load ADDRriU6_2:$addr), m6ImmPred:$addend), + ADDRriU6_2:$addr)]>, + Requires<[HasV4T, UseMEMOP]>; + +// memw(Rs+#u6:2) += #U5 +let AddedComplexity = 30 in +def MEMw_ADDi_MEM_V4 : MEMInst_V4<(outs), + (ins MEMri:$addr, u5Imm:$addend), + "memw($addr) += $addend", + []>, + Requires<[HasV4T, UseMEMOP]>; + +// memw(Rs+#u6:2) -= #U5 +let AddedComplexity = 30 in +def MEMw_SUBi_MEM_V4 : MEMInst_V4<(outs), + (ins MEMri:$addr, u5Imm:$subend), + "memw($addr) -= $subend", + []>, + Requires<[HasV4T, UseMEMOP]>; + +// memw(Rs+#u6:2) += Rt +let AddedComplexity = 30 in +def MEMw_ADDr_MEM_V4 : MEMInst_V4<(outs), + (ins MEMri:$addr, IntRegs:$addend), + "memw($addr) += $addend", + [(store (add (load ADDRriU6_2:$addr), IntRegs:$addend), + ADDRriU6_2:$addr)]>, + Requires<[HasV4T, UseMEMOP]>; + +// memw(Rs+#u6:2) -= Rt +let AddedComplexity = 30 in +def MEMw_SUBr_MEM_V4 : MEMInst_V4<(outs), + (ins MEMri:$addr, IntRegs:$subend), + "memw($addr) -= $subend", + [(store (sub (load ADDRriU6_2:$addr), IntRegs:$subend), + ADDRriU6_2:$addr)]>, + Requires<[HasV4T, UseMEMOP]>; + +// memw(Rs+#u6:2) &= Rt +let AddedComplexity = 30 in +def MEMw_ANDr_MEM_V4 : MEMInst_V4<(outs), + (ins MEMri:$addr, IntRegs:$andend), + "memw($addr) &= $andend", + [(store (and (load ADDRriU6_2:$addr), IntRegs:$andend), + ADDRriU6_2:$addr)]>, + Requires<[HasV4T, UseMEMOP]>; + +// memw(Rs+#u6:2) |= Rt +let AddedComplexity = 30 in +def MEMw_ORr_MEM_V4 : MEMInst_V4<(outs), + (ins MEMri:$addr, IntRegs:$orend), + "memw($addr) |= $orend", + [(store (or (load ADDRriU6_2:$addr), IntRegs:$orend), +ADDRriU6_2:$addr)]>, + Requires<[HasV4T, UseMEMOP]>; + +//===----------------------------------------------------------------------===// +// MEMOP: Halfword +// +// Implemented: +// MEMh_ADDi_indexed_V4 : memw(Rs+#u6:2)+=#U5 +// MEMh_SUBi_indexed_V4 : memw(Rs+#u6:2)-=#U5 +// MEMh_ADDr_indexed_V4 : memw(Rs+#u6:2)+=Rt +// MEMh_SUBr_indexed_V4 : memw(Rs+#u6:2)-=Rt +// MEMh_CLRr_indexed_V4 : memw(Rs+#u6:2)&=Rt +// MEMh_SETr_indexed_V4 : memw(Rs+#u6:2)|=Rt +// MEMh_ADDi_V4 : memw(Rs+#u6:2)+=#U5 +// MEMh_SUBi_V4 : memw(Rs+#u6:2)-=#U5 +// MEMh_ADDr_V4 : memw(Rs+#u6:2)+=Rt +// MEMh_SUBr_V4 : memw(Rs+#u6:2)-=Rt +// MEMh_CLRr_V4 : memw(Rs+#u6:2)&=Rt +// MEMh_SETr_V4 : memw(Rs+#u6:2)|=Rt +// +// Not implemented: +// MEMh_CLRi_indexed_V4 : memw(Rs+#u6:2)=clrbit(#U5) +// MEMh_SETi_indexed_V4 : memw(Rs+#u6:2)=setbit(#U5) +// MEMh_CLRi_V4 : memw(Rs+#u6:2)=clrbit(#U5) +// MEMh_SETi_V4 : memw(Rs+#u6:2)=setbit(#U5) +//===----------------------------------------------------------------------===// + + +// MEMh_ADDSUBi_indexed_V4: +// Pseudo operation for MEMh_ADDi_indexed_V4 and +// MEMh_SUBi_indexed_V4 a later pass will change it +// to the corresponding pattern. +let AddedComplexity = 30 in +def MEMh_ADDSUBi_indexed_MEM_V4 : MEMInst_V4<(outs), + (ins IntRegs:$base, u6_1Imm:$offset, m6Imm:$addend), + "Error; should not emit", + [(truncstorei16 (add (sextloadi16 (add IntRegs:$base, + u6_1ImmPred:$offset)), + m6ImmPred:$addend), + (add IntRegs:$base, u6_1ImmPred:$offset))]>, + Requires<[HasV4T, UseMEMOP]>; + +// memh(Rs+#u6:1) += #U5 +let AddedComplexity = 30 in +def MEMh_ADDi_indexed_MEM_V4 : MEMInst_V4<(outs), + (ins IntRegs:$base, u6_1Imm:$offset, u5Imm:$addend), + "memh($base+#$offset) += $addend", + []>, + Requires<[HasV4T, UseMEMOP]>; + +// memh(Rs+#u6:1) -= #U5 +let AddedComplexity = 30 in +def MEMh_SUBi_indexed_MEM_V4 : MEMInst_V4<(outs), + (ins IntRegs:$base, u6_1Imm:$offset, u5Imm:$subend), + "memh($base+#$offset) -= $subend", + []>, + Requires<[HasV4T, UseMEMOP]>; + +// memh(Rs+#u6:1) += Rt +let AddedComplexity = 30 in +def MEMh_ADDr_indexed_MEM_V4 : MEMInst_V4<(outs), + (ins IntRegs:$base, u6_1Imm:$offset, IntRegs:$addend), + "memh($base+#$offset) += $addend", + [(truncstorei16 (add (sextloadi16 (add IntRegs:$base, + u6_1ImmPred:$offset)), + IntRegs:$addend), + (add IntRegs:$base, u6_1ImmPred:$offset))]>, + Requires<[HasV4T, UseMEMOP]>; + +// memh(Rs+#u6:1) -= Rt +let AddedComplexity = 30 in +def MEMh_SUBr_indexed_MEM_V4 : MEMInst_V4<(outs), + (ins IntRegs:$base, u6_1Imm:$offset, IntRegs:$subend), + "memh($base+#$offset) -= $subend", + [(truncstorei16 (sub (sextloadi16 (add IntRegs:$base, + u6_1ImmPred:$offset)), + IntRegs:$subend), + (add IntRegs:$base, u6_1ImmPred:$offset))]>, + Requires<[HasV4T, UseMEMOP]>; + +// memh(Rs+#u6:1) &= Rt +let AddedComplexity = 30 in +def MEMh_ANDr_indexed_MEM_V4 : MEMInst_V4<(outs), + (ins IntRegs:$base, u6_1Imm:$offset, IntRegs:$andend), + "memh($base+#$offset) += $andend", + [(truncstorei16 (and (sextloadi16 (add IntRegs:$base, + u6_1ImmPred:$offset)), + IntRegs:$andend), + (add IntRegs:$base, u6_1ImmPred:$offset))]>, + Requires<[HasV4T, UseMEMOP]>; + +// memh(Rs+#u6:1) |= Rt +let AddedComplexity = 30 in +def MEMh_ORr_indexed_MEM_V4 : MEMInst_V4<(outs), + (ins IntRegs:$base, u6_1Imm:$offset, IntRegs:$orend), + "memh($base+#$offset) |= $orend", + [(truncstorei16 (or (sextloadi16 (add IntRegs:$base, + u6_1ImmPred:$offset)), + IntRegs:$orend), + (add IntRegs:$base, u6_1ImmPred:$offset))]>, + Requires<[HasV4T, UseMEMOP]>; + +// MEMh_ADDSUBi_V4: +// Pseudo operation for MEMh_ADDi_V4 and MEMh_SUBi_V4 +// a later pass will change it to the right pattern. +let AddedComplexity = 30 in +def MEMh_ADDSUBi_MEM_V4 : MEMInst_V4<(outs), + (ins MEMri:$addr, m6Imm:$addend), + "Error; should not emit", + [(truncstorei16 (add (sextloadi16 ADDRriU6_1:$addr), + m6ImmPred:$addend), ADDRriU6_1:$addr)]>, + Requires<[HasV4T, UseMEMOP]>; + +// memh(Rs+#u6:1) += #U5 +let AddedComplexity = 30 in +def MEMh_ADDi_MEM_V4 : MEMInst_V4<(outs), + (ins MEMri:$addr, u5Imm:$addend), + "memh($addr) += $addend", + []>, + Requires<[HasV4T, UseMEMOP]>; + +// memh(Rs+#u6:1) -= #U5 +let AddedComplexity = 30 in +def MEMh_SUBi_MEM_V4 : MEMInst_V4<(outs), + (ins MEMri:$addr, u5Imm:$subend), + "memh($addr) -= $subend", + []>, + Requires<[HasV4T, UseMEMOP]>; + +// memh(Rs+#u6:1) += Rt +let AddedComplexity = 30 in +def MEMh_ADDr_MEM_V4 : MEMInst_V4<(outs), + (ins MEMri:$addr, IntRegs:$addend), + "memh($addr) += $addend", + [(truncstorei16 (add (sextloadi16 ADDRriU6_1:$addr), + IntRegs:$addend), ADDRriU6_1:$addr)]>, + Requires<[HasV4T, UseMEMOP]>; + +// memh(Rs+#u6:1) -= Rt +let AddedComplexity = 30 in +def MEMh_SUBr_MEM_V4 : MEMInst_V4<(outs), + (ins MEMri:$addr, IntRegs:$subend), + "memh($addr) -= $subend", + [(truncstorei16 (sub (sextloadi16 ADDRriU6_1:$addr), + IntRegs:$subend), ADDRriU6_1:$addr)]>, + Requires<[HasV4T, UseMEMOP]>; + +// memh(Rs+#u6:1) &= Rt +let AddedComplexity = 30 in +def MEMh_ANDr_MEM_V4 : MEMInst_V4<(outs), + (ins MEMri:$addr, IntRegs:$andend), + "memh($addr) &= $andend", + [(truncstorei16 (and (sextloadi16 ADDRriU6_1:$addr), + IntRegs:$andend), ADDRriU6_1:$addr)]>, + Requires<[HasV4T, UseMEMOP]>; + +// memh(Rs+#u6:1) |= Rt +let AddedComplexity = 30 in +def MEMh_ORr_MEM_V4 : MEMInst_V4<(outs), + (ins MEMri:$addr, IntRegs:$orend), + "memh($addr) |= $orend", + [(truncstorei16 (or (sextloadi16 ADDRriU6_1:$addr), + IntRegs:$orend), ADDRriU6_1:$addr)]>, + Requires<[HasV4T, UseMEMOP]>; + + +//===----------------------------------------------------------------------===// +// MEMOP: Byte +// +// Implemented: +// MEMb_ADDi_indexed_V4 : memb(Rs+#u6:0)+=#U5 +// MEMb_SUBi_indexed_V4 : memb(Rs+#u6:0)-=#U5 +// MEMb_ADDr_indexed_V4 : memb(Rs+#u6:0)+=Rt +// MEMb_SUBr_indexed_V4 : memb(Rs+#u6:0)-=Rt +// MEMb_CLRr_indexed_V4 : memb(Rs+#u6:0)&=Rt +// MEMb_SETr_indexed_V4 : memb(Rs+#u6:0)|=Rt +// MEMb_ADDi_V4 : memb(Rs+#u6:0)+=#U5 +// MEMb_SUBi_V4 : memb(Rs+#u6:0)-=#U5 +// MEMb_ADDr_V4 : memb(Rs+#u6:0)+=Rt +// MEMb_SUBr_V4 : memb(Rs+#u6:0)-=Rt +// MEMb_CLRr_V4 : memb(Rs+#u6:0)&=Rt +// MEMb_SETr_V4 : memb(Rs+#u6:0)|=Rt +// +// Not implemented: +// MEMb_CLRi_indexed_V4 : memb(Rs+#u6:0)=clrbit(#U5) +// MEMb_SETi_indexed_V4 : memb(Rs+#u6:0)=setbit(#U5) +// MEMb_CLRi_V4 : memb(Rs+#u6:0)=clrbit(#U5) +// MEMb_SETi_V4 : memb(Rs+#u6:0)=setbit(#U5) +//===----------------------------------------------------------------------===// + + +// MEMb_ADDSUBi_indexed_V4: +// Pseudo operation for MEMb_ADDi_indexed_V4 and +// MEMb_SUBi_indexed_V4 a later pass will change it +// to the corresponding pattern. +let AddedComplexity = 30 in +def MEMb_ADDSUBi_indexed_MEM_V4 : MEMInst_V4<(outs), + (ins IntRegs:$base, u6_0Imm:$offset, m6Imm:$addend), + "Error; should not emit", + [(truncstorei8 (add (sextloadi8 (add IntRegs:$base, + u6_0ImmPred:$offset)), + m6ImmPred:$addend), + (add IntRegs:$base, u6_0ImmPred:$offset))]>, + Requires<[HasV4T, UseMEMOP]>; + +// memb(Rs+#u6:0) += #U5 +let AddedComplexity = 30 in +def MEMb_ADDi_indexed_MEM_V4 : MEMInst_V4<(outs), + (ins IntRegs:$base, u6_0Imm:$offset, u5Imm:$addend), + "memb($base+#$offset) += $addend", + []>, + Requires<[HasV4T, UseMEMOP]>; + +// memb(Rs+#u6:0) -= #U5 +let AddedComplexity = 30 in +def MEMb_SUBi_indexed_MEM_V4 : MEMInst_V4<(outs), + (ins IntRegs:$base, u6_0Imm:$offset, u5Imm:$subend), + "memb($base+#$offset) -= $subend", + []>, + Requires<[HasV4T, UseMEMOP]>; + +// memb(Rs+#u6:0) += Rt +let AddedComplexity = 30 in +def MEMb_ADDr_indexed_MEM_V4 : MEMInst_V4<(outs), + (ins IntRegs:$base, u6_0Imm:$offset, IntRegs:$addend), + "memb($base+#$offset) += $addend", + [(truncstorei8 (add (sextloadi8 (add IntRegs:$base, + u6_0ImmPred:$offset)), + IntRegs:$addend), + (add IntRegs:$base, u6_0ImmPred:$offset))]>, + Requires<[HasV4T, UseMEMOP]>; + +// memb(Rs+#u6:0) -= Rt +let AddedComplexity = 30 in +def MEMb_SUBr_indexed_MEM_V4 : MEMInst_V4<(outs), + (ins IntRegs:$base, u6_0Imm:$offset, IntRegs:$subend), + "memb($base+#$offset) -= $subend", + [(truncstorei8 (sub (sextloadi8 (add IntRegs:$base, + u6_0ImmPred:$offset)), + IntRegs:$subend), + (add IntRegs:$base, u6_0ImmPred:$offset))]>, + Requires<[HasV4T, UseMEMOP]>; + +// memb(Rs+#u6:0) &= Rt +let AddedComplexity = 30 in +def MEMb_ANDr_indexed_MEM_V4 : MEMInst_V4<(outs), + (ins IntRegs:$base, u6_0Imm:$offset, IntRegs:$andend), + "memb($base+#$offset) += $andend", + [(truncstorei8 (and (sextloadi8 (add IntRegs:$base, + u6_0ImmPred:$offset)), + IntRegs:$andend), + (add IntRegs:$base, u6_0ImmPred:$offset))]>, + Requires<[HasV4T, UseMEMOP]>; + +// memb(Rs+#u6:0) |= Rt +let AddedComplexity = 30 in +def MEMb_ORr_indexed_MEM_V4 : MEMInst_V4<(outs), + (ins IntRegs:$base, u6_0Imm:$offset, IntRegs:$orend), + "memb($base+#$offset) |= $orend", + [(truncstorei8 (or (sextloadi8 (add IntRegs:$base, + u6_0ImmPred:$offset)), + IntRegs:$orend), + (add IntRegs:$base, u6_0ImmPred:$offset))]>, + Requires<[HasV4T, UseMEMOP]>; + +// MEMb_ADDSUBi_V4: +// Pseudo operation for MEMb_ADDi_V4 and MEMb_SUBi_V4 +// a later pass will change it to the right pattern. +let AddedComplexity = 30 in +def MEMb_ADDSUBi_MEM_V4 : MEMInst_V4<(outs), + (ins MEMri:$addr, m6Imm:$addend), + "Error; should not emit", + [(truncstorei8 (add (sextloadi8 ADDRriU6_0:$addr), + m6ImmPred:$addend), ADDRriU6_0:$addr)]>, + Requires<[HasV4T, UseMEMOP]>; + +// memb(Rs+#u6:0) += #U5 +let AddedComplexity = 30 in +def MEMb_ADDi_MEM_V4 : MEMInst_V4<(outs), + (ins MEMri:$addr, u5Imm:$addend), + "memb($addr) += $addend", + []>, + Requires<[HasV4T, UseMEMOP]>; + +// memb(Rs+#u6:0) -= #U5 +let AddedComplexity = 30 in +def MEMb_SUBi_MEM_V4 : MEMInst_V4<(outs), + (ins MEMri:$addr, u5Imm:$subend), + "memb($addr) -= $subend", + []>, + Requires<[HasV4T, UseMEMOP]>; + +// memb(Rs+#u6:0) += Rt +let AddedComplexity = 30 in +def MEMb_ADDr_MEM_V4 : MEMInst_V4<(outs), + (ins MEMri:$addr, IntRegs:$addend), + "memb($addr) += $addend", + [(truncstorei8 (add (sextloadi8 ADDRriU6_0:$addr), + IntRegs:$addend), ADDRriU6_0:$addr)]>, + Requires<[HasV4T, UseMEMOP]>; + +// memb(Rs+#u6:0) -= Rt +let AddedComplexity = 30 in +def MEMb_SUBr_MEM_V4 : MEMInst_V4<(outs), + (ins MEMri:$addr, IntRegs:$subend), + "memb($addr) -= $subend", + [(truncstorei8 (sub (sextloadi8 ADDRriU6_0:$addr), + IntRegs:$subend), ADDRriU6_0:$addr)]>, + Requires<[HasV4T, UseMEMOP]>; + +// memb(Rs+#u6:0) &= Rt +let AddedComplexity = 30 in +def MEMb_ANDr_MEM_V4 : MEMInst_V4<(outs), + (ins MEMri:$addr, IntRegs:$andend), + "memb($addr) &= $andend", + [(truncstorei8 (and (sextloadi8 ADDRriU6_0:$addr), + IntRegs:$andend), ADDRriU6_0:$addr)]>, + Requires<[HasV4T, UseMEMOP]>; + +// memb(Rs+#u6:0) |= Rt +let AddedComplexity = 30 in +def MEMb_ORr_MEM_V4 : MEMInst_V4<(outs), + (ins MEMri:$addr, IntRegs:$orend), + "memb($addr) |= $orend", + [(truncstorei8 (or (sextloadi8 ADDRriU6_0:$addr), + IntRegs:$orend), ADDRriU6_0:$addr)]>, + Requires<[HasV4T, UseMEMOP]>; + + +//===----------------------------------------------------------------------===// +// XTYPE/PRED + +//===----------------------------------------------------------------------===// + +// Hexagon V4 only supports these flavors of byte/half compare instructions: +// EQ/GT/GTU. Other flavors like GE/GEU/LT/LTU/LE/LEU are not supported by +// hardware. However, compiler can still implement these patterns through +// appropriate patterns combinations based on current implemented patterns. +// The implemented patterns are: EQ/GT/GTU. +// Missing patterns are: GE/GEU/LT/LTU/LE/LEU. + +// Pd=cmpb.eq(Rs,#u8) +let isCompare = 1 in +def CMPbEQri_V4 : MInst<(outs PredRegs:$dst), + (ins IntRegs:$src1, u8Imm:$src2), + "$dst = cmpb.eq($src1, #$src2)", + [(set PredRegs:$dst, (seteq (and IntRegs:$src1, 255), + u8ImmPred:$src2))]>, + Requires<[HasV4T]>; + +// Pd=cmpb.eq(Rs,Rt) +let isCompare = 1 in +def CMPbEQrr_ubub_V4 : MInst<(outs PredRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2), + "$dst = cmpb.eq($src1, $src2)", + [(set PredRegs:$dst, (seteq (and (xor IntRegs:$src1, + IntRegs:$src2), + 255), + 0))]>, + Requires<[HasV4T]>; + +// Pd=cmpb.eq(Rs,Rt) +let isCompare = 1 in +def CMPbEQrr_sbsb_V4 : MInst<(outs PredRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2), + "$dst = cmpb.eq($src1, $src2)", + [(set PredRegs:$dst, (seteq (shl IntRegs:$src1, (i32 24)), + (shl IntRegs:$src2, (i32 24))))]>, + Requires<[HasV4T]>; + +// Pd=cmpb.gt(Rs,#s8) +let isCompare = 1 in +def CMPbGTri_V4 : MInst<(outs PredRegs:$dst), + (ins IntRegs:$src1, s32Imm:$src2), + "$dst = cmpb.gt($src1, #$src2)", + [(set PredRegs:$dst, (setgt (shl IntRegs:$src1, (i32 24)), + s32_24ImmPred:$src2))]>, + Requires<[HasV4T]>; + +// Pd=cmpb.gt(Rs,Rt) +let isCompare = 1 in +def CMPbGTrr_V4 : MInst<(outs PredRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2), + "$dst = cmpb.gt($src1, $src2)", + [(set PredRegs:$dst, (setgt (shl IntRegs:$src1, (i32 24)), + (shl IntRegs:$src2, (i32 24))))]>, + Requires<[HasV4T]>; + +// Pd=cmpb.gtu(Rs,#u7) +let isCompare = 1 in +def CMPbGTUri_V4 : MInst<(outs PredRegs:$dst), + (ins IntRegs:$src1, u7Imm:$src2), + "$dst = cmpb.gtu($src1, #$src2)", + [(set PredRegs:$dst, (setugt (and IntRegs:$src1, 255), + u7ImmPred:$src2))]>, + Requires<[HasV4T]>; + +// Pd=cmpb.gtu(Rs,Rt) +let isCompare = 1 in +def CMPbGTUrr_V4 : MInst<(outs PredRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2), + "$dst = cmpb.gtu($src1, $src2)", + [(set PredRegs:$dst, (setugt (and IntRegs:$src1, 255), + (and IntRegs:$src2, 255)))]>, + Requires<[HasV4T]>; + +// Signed half compare(.eq) ri. +// Pd=cmph.eq(Rs,#s8) +let isCompare = 1 in +def CMPhEQri_V4 : MInst<(outs PredRegs:$dst), + (ins IntRegs:$src1, u16Imm:$src2), + "$dst = cmph.eq($src1, #$src2)", + [(set PredRegs:$dst, (seteq (and IntRegs:$src1, 65535), + u16_s8ImmPred:$src2))]>, + Requires<[HasV4T]>; + +// Signed half compare(.eq) rr. +// Case 1: xor + and, then compare: +// r0=xor(r0,r1) +// r0=and(r0,#0xffff) +// p0=cmp.eq(r0,#0) +// Pd=cmph.eq(Rs,Rt) +let isCompare = 1 in +def CMPhEQrr_xor_V4 : MInst<(outs PredRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2), + "$dst = cmph.eq($src1, $src2)", + [(set PredRegs:$dst, (seteq (and (xor IntRegs:$src1, + IntRegs:$src2), + 65535), + 0))]>, + Requires<[HasV4T]>; + +// Signed half compare(.eq) rr. +// Case 2: shift left 16 bits then compare: +// r0=asl(r0,16) +// r1=asl(r1,16) +// p0=cmp.eq(r0,r1) +// Pd=cmph.eq(Rs,Rt) +let isCompare = 1 in +def CMPhEQrr_shl_V4 : MInst<(outs PredRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2), + "$dst = cmph.eq($src1, $src2)", + [(set PredRegs:$dst, (seteq (shl IntRegs:$src1, (i32 16)), + (shl IntRegs:$src2, (i32 16))))]>, + Requires<[HasV4T]>; + +// Signed half compare(.gt) ri. +// Pd=cmph.gt(Rs,#s8) +let isCompare = 1 in +def CMPhGTri_V4 : MInst<(outs PredRegs:$dst), + (ins IntRegs:$src1, s32Imm:$src2), + "$dst = cmph.gt($src1, #$src2)", + [(set PredRegs:$dst, (setgt (shl IntRegs:$src1, (i32 16)), + s32_16s8ImmPred:$src2))]>, + Requires<[HasV4T]>; + +// Signed half compare(.gt) rr. +// Pd=cmph.gt(Rs,Rt) +let isCompare = 1 in +def CMPhGTrr_shl_V4 : MInst<(outs PredRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2), + "$dst = cmph.gt($src1, $src2)", + [(set PredRegs:$dst, (setgt (shl IntRegs:$src1, (i32 16)), + (shl IntRegs:$src2, (i32 16))))]>, + Requires<[HasV4T]>; + +// Unsigned half compare rr (.gtu). +// Pd=cmph.gtu(Rs,Rt) +let isCompare = 1 in +def CMPhGTUrr_V4 : MInst<(outs PredRegs:$dst), + (ins IntRegs:$src1, IntRegs:$src2), + "$dst = cmph.gtu($src1, $src2)", + [(set PredRegs:$dst, (setugt (and IntRegs:$src1, 65535), + (and IntRegs:$src2, 65535)))]>, + Requires<[HasV4T]>; + +// Unsigned half compare ri (.gtu). +// Pd=cmph.gtu(Rs,#u7) +let isCompare = 1 in +def CMPhGTUri_V4 : MInst<(outs PredRegs:$dst), + (ins IntRegs:$src1, u7Imm:$src2), + "$dst = cmph.gtu($src1, #$src2)", + [(set PredRegs:$dst, (setugt (and IntRegs:$src1, 65535), + u7ImmPred:$src2))]>, + Requires<[HasV4T]>; + +//===----------------------------------------------------------------------===// +// XTYPE/PRED - +//===----------------------------------------------------------------------===// + +//Deallocate frame and return. +// dealloc_return +let isReturn = 1, isTerminator = 1, isBarrier = 1, isPredicable = 1, + Defs = [R29, R30, R31, PC], Uses = [R29, R31], neverHasSideEffects = 1 in { + def DEALLOC_RET_V4 : NVInst_V4<(outs), (ins i32imm:$amt1), + "dealloc_return", + []>, + Requires<[HasV4T]>; +} + +// if (Ps) dealloc_return +let isReturn = 1, isTerminator = 1, + Defs = [R29, R30, R31, PC], Uses = [R29, R31], neverHasSideEffects = 1 in { + def DEALLOC_RET_cPt_V4 : NVInst_V4<(outs), (ins PredRegs:$src1, i32imm:$amt1), + "if ($src1) dealloc_return", + []>, + Requires<[HasV4T]>; +} + +// if (!Ps) dealloc_return +let isReturn = 1, isTerminator = 1, + Defs = [R29, R30, R31, PC], Uses = [R29, R31], neverHasSideEffects = 1 in { + def DEALLOC_RET_cNotPt_V4 : NVInst_V4<(outs), (ins PredRegs:$src1, + i32imm:$amt1), + "if (!$src1) dealloc_return", + []>, + Requires<[HasV4T]>; +} + +// if (Ps.new) dealloc_return:nt +let isReturn = 1, isTerminator = 1, + Defs = [R29, R30, R31, PC], Uses = [R29, R31], neverHasSideEffects = 1 in { + def DEALLOC_RET_cdnPnt_V4 : NVInst_V4<(outs), (ins PredRegs:$src1, + i32imm:$amt1), + "if ($src1.new) dealloc_return:nt", + []>, + Requires<[HasV4T]>; +} + +// if (!Ps.new) dealloc_return:nt +let isReturn = 1, isTerminator = 1, + Defs = [R29, R30, R31, PC], Uses = [R29, R31], neverHasSideEffects = 1 in { + def DEALLOC_RET_cNotdnPnt_V4 : NVInst_V4<(outs), (ins PredRegs:$src1, + i32imm:$amt1), + "if (!$src1.new) dealloc_return:nt", + []>, + Requires<[HasV4T]>; +} + +// if (Ps.new) dealloc_return:t +let isReturn = 1, isTerminator = 1, + Defs = [R29, R30, R31, PC], Uses = [R29, R31], neverHasSideEffects = 1 in { + def DEALLOC_RET_cdnPt_V4 : NVInst_V4<(outs), (ins PredRegs:$src1, + i32imm:$amt1), + "if ($src1.new) dealloc_return:t", + []>, + Requires<[HasV4T]>; +} + +// if (!Ps.new) dealloc_return:nt +let isReturn = 1, isTerminator = 1, + Defs = [R29, R30, R31, PC], Uses = [R29, R31], neverHasSideEffects = 1 in { + def DEALLOC_RET_cNotdnPt_V4 : NVInst_V4<(outs), (ins PredRegs:$src1, + i32imm:$amt1), + "if (!$src1.new) dealloc_return:t", + []>, + Requires<[HasV4T]>; +} diff --git a/lib/Target/Hexagon/HexagonIntrinsics.td b/lib/Target/Hexagon/HexagonIntrinsics.td new file mode 100644 index 0000000000..1328ebab57 --- /dev/null +++ b/lib/Target/Hexagon/HexagonIntrinsics.td @@ -0,0 +1,3462 @@ +//===- HexagonIntrinsics.td - Instruction intrinsics -------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// This is populated based on the following specs: +// Hexagon V2 Architecture +// Application-Level Specification +// 80-V9418-8 Rev. B +// March 4, 2008 +//===----------------------------------------------------------------------===// + +// +// ALU 32 types. +// + +class qi_ALU32_sisi<string opc, Intrinsic IntID> + : ALU32_rr<(outs PredRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2)")), + [(set PredRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class qi_ALU32_sis10<string opc, Intrinsic IntID> + : ALU32_rr<(outs PredRegs:$dst), (ins IntRegs:$src1, s10Imm:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, #$src2)")), + [(set PredRegs:$dst, (IntID IntRegs:$src1, imm:$src2))]>; + +class qi_ALU32_sis8<string opc, Intrinsic IntID> + : ALU32_rr<(outs PredRegs:$dst), (ins IntRegs:$src1, s8Imm:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, #$src2)")), + [(set PredRegs:$dst, (IntID IntRegs:$src1, imm:$src2))]>; + +class qi_ALU32_siu8<string opc, Intrinsic IntID> + : ALU32_rr<(outs PredRegs:$dst), (ins IntRegs:$src1, u8Imm:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, #$src2)")), + [(set PredRegs:$dst, (IntID IntRegs:$src1, imm:$src2))]>; + +class qi_ALU32_siu9<string opc, Intrinsic IntID> + : ALU32_rr<(outs PredRegs:$dst), (ins IntRegs:$src1, u9Imm:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, #$src2)")), + [(set PredRegs:$dst, (IntID IntRegs:$src1, imm:$src2))]>; + +class si_ALU32_qisisi<string opc, Intrinsic IntID> + : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2, + IntRegs:$src3), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2, $src3)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2, + IntRegs:$src3))]>; + +class si_ALU32_qis8si<string opc, Intrinsic IntID> + : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, s8Imm:$src2, + IntRegs:$src3), + !strconcat("$dst = ", !strconcat(opc , "($src1, #$src2, $src3)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, imm:$src2, + IntRegs:$src3))]>; + +class si_ALU32_qisis8<string opc, Intrinsic IntID> + : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2, + s8Imm:$src3), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2, #$src3)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2, + imm:$src3))]>; + +class si_ALU32_qis8s8<string opc, Intrinsic IntID> + : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, s8Imm:$src2, s8Imm:$src3), + !strconcat("$dst = ", !strconcat(opc , "($src1, #$src2, #$src3)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, imm:$src2, imm:$src3))]>; + +class si_ALU32_sisi<string opc, Intrinsic IntID> + : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_ALU32_sisi_sat<string opc, Intrinsic IntID> + : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2):sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_ALU32_sisi_rnd<string opc, Intrinsic IntID> + : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2):rnd")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_ALU32_sis16<string opc, Intrinsic IntID> + : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, s16Imm:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, #$src2)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, imm:$src2))]>; + +class si_ALU32_sis10<string opc, Intrinsic IntID> + : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, s10Imm:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, #$src2)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, imm:$src2))]>; + +class si_ALU32_s10si<string opc, Intrinsic IntID> + : ALU32_rr<(outs IntRegs:$dst), (ins s10Imm:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "(#$src1, $src2)")), + [(set IntRegs:$dst, (IntID imm:$src1, IntRegs:$src2))]>; + +class si_lo_ALU32_siu16<string opc, Intrinsic IntID> + : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, u16Imm:$src2), + !strconcat("$dst.l = ", !strconcat(opc , "#$src2")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, imm:$src2))]>; + +class si_hi_ALU32_siu16<string opc, Intrinsic IntID> + : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, u16Imm:$src2), + !strconcat("$dst.h = ", !strconcat(opc , "#$src2")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, imm:$src2))]>; + +class si_ALU32_s16<string opc, Intrinsic IntID> + : ALU32_rr<(outs IntRegs:$dst), (ins s16Imm:$src1), + !strconcat("$dst = ", !strconcat(opc , "#$src1")), + [(set IntRegs:$dst, (IntID imm:$src1))]>; + +class di_ALU32_s8<string opc, Intrinsic IntID> + : ALU32_rr<(outs DoubleRegs:$dst), (ins s8Imm:$src1), + !strconcat("$dst = ", !strconcat(opc , "#$src1")), + [(set DoubleRegs:$dst, (IntID imm:$src1))]>; + +class di_ALU64_di<string opc, Intrinsic IntID> + : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src), + !strconcat("$dst = ", !strconcat(opc , "$src")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$src))]>; + +class si_ALU32_si<string opc, Intrinsic IntID> + : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src), + !strconcat("$dst = ", !strconcat(opc , "($src)")), + [(set IntRegs:$dst, (IntID IntRegs:$src))]>; + +class si_ALU32_si_tfr<string opc, Intrinsic IntID> + : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src), + !strconcat("$dst = ", !strconcat(opc , "$src")), + [(set IntRegs:$dst, (IntID IntRegs:$src))]>; + +// +// ALU 64 types. +// + +class si_ALU64_si_sat<string opc, Intrinsic IntID> + : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src), + !strconcat("$dst = ", !strconcat(opc , "($src):sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src))]>; + +class si_ALU64_didi<string opc, Intrinsic IntID> + : ALU64_rr<(outs IntRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2)")), + [(set IntRegs:$dst, (IntID DoubleRegs:$src1, DoubleRegs:$src2))]>; + +class di_ALU64_sidi<string opc, Intrinsic IntID> + : ALU64_rr<(outs DoubleRegs:$dst), (ins IntRegs:$src1, DoubleRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2)")), + [(set DoubleRegs:$dst, (IntID IntRegs:$src1, DoubleRegs:$src2))]>; + +class di_ALU64_didi<string opc, Intrinsic IntID> + : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$src1, + DoubleRegs:$src2))]>; + +class di_ALU64_qididi<string opc, Intrinsic IntID> + : ALU64_rr<(outs DoubleRegs:$dst), (ins IntRegs:$src1, DoubleRegs:$src2, + DoubleRegs:$src3), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2, $src3)")), + [(set DoubleRegs:$dst, (IntID IntRegs:$src1, DoubleRegs:$src2, + DoubleRegs:$src3))]>; + +class di_ALU64_sisi<string opc, Intrinsic IntID> + : ALU64_rr<(outs DoubleRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2)")), + [(set DoubleRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class di_ALU64_didi_sat<string opc, Intrinsic IntID> + : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2):sat")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$src1, + DoubleRegs:$src2))]>; + +class di_ALU64_didi_rnd<string opc, Intrinsic IntID> + : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2):rnd")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$src1, + DoubleRegs:$src2))]>; + +class di_ALU64_didi_crnd<string opc, Intrinsic IntID> + : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2):crnd")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$src1, + DoubleRegs:$src2))]>; + +class di_ALU64_didi_rnd_sat<string opc, Intrinsic IntID> + : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2):rnd:sat")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$src1, + DoubleRegs:$src2))]>; + +class di_ALU64_didi_crnd_sat<string opc, Intrinsic IntID> + : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2):crnd:sat")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$src1, + DoubleRegs:$src2))]>; + +class qi_ALU64_didi<string opc, Intrinsic IntID> + : ALU64_rr<(outs PredRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2)")), + [(set PredRegs:$dst, (IntID DoubleRegs:$src1, DoubleRegs:$src2))]>; + +class si_ALU64_sisi<string opc, Intrinsic IntID> + : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_ALU64_sisi_sat_lh<string opc, Intrinsic IntID> + : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.L, $src2.H):sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_ALU64_sisi_l16_sat_hh<string opc, Intrinsic IntID> + : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.H, $src2.H):sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_ALU64_sisi_l16_sat_lh<string opc, Intrinsic IntID> + : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.L, $src2.H):sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_ALU64_sisi_l16_sat_hl<string opc, Intrinsic IntID> + : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.H, $src2.L):sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_ALU64_sisi_l16_sat_ll<string opc, Intrinsic IntID> + : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.L, $src2.L):sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_ALU64_sisi_l16_hh<string opc, Intrinsic IntID> + : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.H, $src2.H)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_ALU64_sisi_l16_hl<string opc, Intrinsic IntID> + : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.H, $src2.L)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_ALU64_sisi_l16_lh<string opc, Intrinsic IntID> + : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.L, $src2.H)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_ALU64_sisi_l16_ll<string opc, Intrinsic IntID> + : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.L, $src2.L)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_ALU64_sisi_h16_sat_hh<string opc, Intrinsic IntID> + : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , + "($src1.H, $src2.H):sat:<<16")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_ALU64_sisi_h16_sat_lh<string opc, Intrinsic IntID> + : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , + "($src1.L, $src2.H):sat:<<16")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_ALU64_sisi_h16_sat_hl<string opc, Intrinsic IntID> + : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , + "($src1.H, $src2.L):sat:<<16")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_ALU64_sisi_h16_sat_ll<string opc, Intrinsic IntID> + : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , + "($src1.L, $src2.L):sat:<<16")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_ALU64_sisi_h16_hh<string opc, Intrinsic IntID> + : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.H, $src2.H):<<16")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_ALU64_sisi_h16_hl<string opc, Intrinsic IntID> + : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.H, $src2.L):<<16")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_ALU64_sisi_h16_lh<string opc, Intrinsic IntID> + : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.L, $src2.H):<<16")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_ALU64_sisi_h16_ll<string opc, Intrinsic IntID> + : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.L, $src2.L):<<16")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_ALU64_sisi_lh<string opc, Intrinsic IntID> + : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.L, $src2.H)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_ALU64_sisi_ll<string opc, Intrinsic IntID> + : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.L, $src2.L)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_ALU64_sisi_sat<string opc, Intrinsic IntID> + : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2):sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +// +// SInst classes. +// + +class qi_SInst_qi<string opc, Intrinsic IntID> + : SInst<(outs PredRegs:$dst), (ins IntRegs:$src), + !strconcat("$dst = ", !strconcat(opc , "($src)")), + [(set PredRegs:$dst, (IntID IntRegs:$src))]>; + +class qi_SInst_qi_pxfer<string opc, Intrinsic IntID> + : SInst<(outs PredRegs:$dst), (ins IntRegs:$src), + !strconcat("$dst = ", !strconcat(opc , "$src")), + [(set PredRegs:$dst, (IntID IntRegs:$src))]>; + +class qi_SInst_qiqi<string opc, Intrinsic IntID> + : SInst<(outs PredRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2)")), + [(set PredRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class qi_SInst_qiqi_neg<string opc, Intrinsic IntID> + : SInst<(outs PredRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, !$src2)")), + [(set PredRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class di_SInst_di<string opc, Intrinsic IntID> + : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src), + !strconcat("$dst = ", !strconcat(opc , "($src)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$src))]>; + +class di_SInst_di_sat<string opc, Intrinsic IntID> + : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src), + !strconcat("$dst = ", !strconcat(opc , "($src):sat")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$src))]>; + +class si_SInst_di<string opc, Intrinsic IntID> + : SInst<(outs IntRegs:$dst), (ins DoubleRegs:$src), + !strconcat("$dst = ", !strconcat(opc , "($src)")), + [(set IntRegs:$dst, (IntID DoubleRegs:$src))]>; + +class si_SInst_di_sat<string opc, Intrinsic IntID> + : SInst<(outs IntRegs:$dst), (ins DoubleRegs:$src), + !strconcat("$dst = ", !strconcat(opc , "($src):sat")), + [(set IntRegs:$dst, (IntID DoubleRegs:$src))]>; + +class di_SInst_disi<string opc, Intrinsic IntID> + : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$src1, IntRegs:$src2))]>; + +class di_SInst_didi<string opc, Intrinsic IntID> + : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$src1, DoubleRegs:$src2))]>; + +class di_SInst_si<string opc, Intrinsic IntID> + : SInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1), + !strconcat("$dst = ", !strconcat(opc , "($src1)")), + [(set DoubleRegs:$dst, (IntID IntRegs:$src1))]>; + +class si_SInst_sisiu3<string opc, Intrinsic IntID> + : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2, u3Imm:$src3), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2, #$src3)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2, + imm:$src3))]>; + +class si_SInst_diu5<string opc, Intrinsic IntID> + : SInst<(outs IntRegs:$dst), (ins DoubleRegs:$src1, u5Imm:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, #$src2)")), + [(set IntRegs:$dst, (IntID DoubleRegs:$src1, imm:$src2))]>; + +class si_SInst_disi<string opc, Intrinsic IntID> + : SInst<(outs IntRegs:$dst), (ins DoubleRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2)")), + [(set IntRegs:$dst, (IntID DoubleRegs:$src1, IntRegs:$src2))]>; + +class si_SInst_sidi<string opc, Intrinsic IntID> + : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, DoubleRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, DoubleRegs:$src2))]>; + +class di_SInst_disisi<string opc, Intrinsic IntID> + : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, IntRegs:$src2, + IntRegs:$src3), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2, $src3)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$src1, IntRegs:$src2, + IntRegs:$src3))]>; + +class di_SInst_sisi<string opc, Intrinsic IntID> + : SInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2)")), + [(set DoubleRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class qi_SInst_siu5<string opc, Intrinsic IntID> + : SInst<(outs PredRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, #$src2)")), + [(set PredRegs:$dst, (IntID IntRegs:$src1, imm:$src2))]>; + +class qi_SInst_siu6<string opc, Intrinsic IntID> + : SInst<(outs PredRegs:$dst), (ins IntRegs:$src1, u6Imm:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, #$src2)")), + [(set PredRegs:$dst, (IntID IntRegs:$src1, imm:$src2))]>; + +class qi_SInst_sisi<string opc, Intrinsic IntID> + : SInst<(outs PredRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2)")), + [(set PredRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_SInst_si<string opc, Intrinsic IntID> + : SInst<(outs IntRegs:$dst), (ins IntRegs:$src), + !strconcat("$dst = ", !strconcat(opc , "($src)")), + [(set IntRegs:$dst, (IntID IntRegs:$src))]>; + +class si_SInst_si_sat<string opc, Intrinsic IntID> + : SInst<(outs IntRegs:$dst), (ins IntRegs:$src), + !strconcat("$dst = ", !strconcat(opc , "($src):sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src))]>; + +class di_SInst_qi<string opc, Intrinsic IntID> + : SInst<(outs DoubleRegs:$dst), (ins IntRegs:$src), + !strconcat("$dst = ", !strconcat(opc , "($src)")), + [(set DoubleRegs:$dst, (IntID IntRegs:$src))]>; + +class si_SInst_qi<string opc, Intrinsic IntID> + : SInst<(outs IntRegs:$dst), (ins IntRegs:$src), + !strconcat("$dst = ", !strconcat(opc , "$src")), + [(set IntRegs:$dst, (IntID IntRegs:$src))]>; + +class si_SInst_qiqi<string opc, Intrinsic IntID> + : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class qi_SInst_si<string opc, Intrinsic IntID> + : SInst<(outs PredRegs:$dst), (ins IntRegs:$src), + !strconcat("$dst = ", !strconcat(opc , "$src")), + [(set PredRegs:$dst, (IntID IntRegs:$src))]>; + +class si_SInst_sisi<string opc, Intrinsic IntID> + : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class di_SInst_diu6<string opc, Intrinsic IntID> + : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, u6Imm:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, #$src2)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$src1, imm:$src2))]>; + +class si_SInst_siu5<string opc, Intrinsic IntID> + : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, #$src2)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, imm:$src2))]>; + +class si_SInst_siu5_rnd<string opc, Intrinsic IntID> + : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, #$src2):rnd")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, imm:$src2))]>; + +class si_SInst_siu5u5<string opc, Intrinsic IntID> + : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2, u5Imm:$src3), + !strconcat("$dst = ", !strconcat(opc , "($src1, #$src2, #$src3)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, imm:$src2, imm:$src3))]>; + +class si_SInst_sisisi_acc<string opc, Intrinsic IntID> + : SInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", !strconcat(opc , "($src1, $src2)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_SInst_sisisi_nac<string opc, Intrinsic IntID> + : SInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , "($src1, $src2)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_SInst_didisi_acc<string opc, Intrinsic IntID> + : SInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, DoubleRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", !strconcat(opc , "($src1, $src2)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, + DoubleRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_SInst_didisi_nac<string opc, Intrinsic IntID> + : SInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, DoubleRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , "($src1, $src2)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, + DoubleRegs:$src1, IntRegs:$src2))], + "$dst2 = $dst">; + +class si_SInst_sisiu5u5<string opc, Intrinsic IntID> + : SInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + u5Imm:$src2, u5Imm:$src3), + !strconcat("$dst = ", !strconcat(opc , + "($src1, #$src2, #$src3)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + imm:$src2, imm:$src3))], + "$dst2 = $dst">; + +class si_SInst_sisidi<string opc, Intrinsic IntID> + : SInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + DoubleRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + DoubleRegs:$src2))], + "$dst2 = $dst">; + +class di_SInst_didiu6u6<string opc, Intrinsic IntID> + : SInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, DoubleRegs:$src1, + u6Imm:$src2, u6Imm:$src3), + !strconcat("$dst = ", !strconcat(opc , + "($src1, #$src2, #$src3)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, DoubleRegs:$src1, + imm:$src2, imm:$src3))], + "$dst2 = $dst">; + +class di_SInst_dididi<string opc, Intrinsic IntID> + : SInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, DoubleRegs:$src1, + DoubleRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, + DoubleRegs:$src1, + DoubleRegs:$src2))], + "$dst2 = $dst">; + +class di_SInst_diu6u6<string opc, Intrinsic IntID> + : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, u6Imm:$src2, + u6Imm:$src3), + !strconcat("$dst = ", !strconcat(opc , "($src1, #$src2, #$src3)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$src1, imm:$src2, + imm:$src3))]>; + +class di_SInst_didisi<string opc, Intrinsic IntID> + : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2, + IntRegs:$src3), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2, $src3)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$src1, DoubleRegs:$src2, + IntRegs:$src3))]>; + +class di_SInst_didiqi<string opc, Intrinsic IntID> + : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2, + IntRegs:$src3), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2, $src3)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$src1, DoubleRegs:$src2, + IntRegs:$src3))]>; + +class di_SInst_didiu3<string opc, Intrinsic IntID> + : SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2, + u3Imm:$src3), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2, #$src3)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$src1, DoubleRegs:$src2, + imm:$src3))]>; + +class di_SInst_didisi_or<string opc, Intrinsic IntID> + : SInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, DoubleRegs:$src1, + IntRegs:$src2), + !strconcat("$dst |= ", !strconcat(opc , "($src1, $src2)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, DoubleRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_SInst_didisi_and<string opc, Intrinsic IntID> + : SInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, DoubleRegs:$src1, + IntRegs:$src2), + !strconcat("$dst &= ", !strconcat(opc , "($src1, $src2)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, DoubleRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_SInst_didiu6_and<string opc, Intrinsic IntID> + : SInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, DoubleRegs:$src1, + u6Imm:$src2), + !strconcat("$dst &= ", !strconcat(opc , "($src1, #$src2)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, DoubleRegs:$src1, + imm:$src2))], + "$dst2 = $dst">; + +class di_SInst_didiu6_or<string opc, Intrinsic IntID> + : SInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, DoubleRegs:$src1, + u6Imm:$src2), + !strconcat("$dst |= ", !strconcat(opc , "($src1, #$src2)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, DoubleRegs:$src1, + imm:$src2))], + "$dst2 = $dst">; + +class di_SInst_didiu6_xor<string opc, Intrinsic IntID> + : SInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, DoubleRegs:$src1, + u6Imm:$src2), + !strconcat("$dst ^= ", !strconcat(opc , "($src1, #$src2)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, DoubleRegs:$src1, + imm:$src2))], + "$dst2 = $dst">; + +class si_SInst_sisisi_and<string opc, Intrinsic IntID> + : SInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst &= ", !strconcat(opc , "($src1, $src2)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_SInst_sisisi_or<string opc, Intrinsic IntID> + : SInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst |= ", !strconcat(opc , "($src1, $src2)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + + +class si_SInst_sisiu5_and<string opc, Intrinsic IntID> + : SInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + u5Imm:$src2), + !strconcat("$dst &= ", !strconcat(opc , "($src1, #$src2)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + imm:$src2))], + "$dst2 = $dst">; + +class si_SInst_sisiu5_or<string opc, Intrinsic IntID> + : SInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + u5Imm:$src2), + !strconcat("$dst |= ", !strconcat(opc , "($src1, #$src2)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + imm:$src2))], + "$dst2 = $dst">; + +class si_SInst_sisiu5_xor<string opc, Intrinsic IntID> + : SInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + u5Imm:$src2), + !strconcat("$dst ^= ", !strconcat(opc , "($src1, #$src2)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + imm:$src2))], + "$dst2 = $dst">; + +class si_SInst_sisiu5_acc<string opc, Intrinsic IntID> + : SInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + u5Imm:$src2), + !strconcat("$dst += ", !strconcat(opc , "($src1, #$src2)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + imm:$src2))], + "$dst2 = $dst">; + +class si_SInst_sisiu5_nac<string opc, Intrinsic IntID> + : SInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + u5Imm:$src2), + !strconcat("$dst -= ", !strconcat(opc , "($src1, #$src2)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + imm:$src2))], + "$dst2 = $dst">; + +class di_SInst_didiu6_acc<string opc, Intrinsic IntID> + : SInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, DoubleRegs:$src1, + u5Imm:$src2), + !strconcat("$dst += ", !strconcat(opc , "($src1, #$src2)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, + DoubleRegs:$src1, imm:$src2))], + "$dst2 = $dst">; + +class di_SInst_didiu6_nac<string opc, Intrinsic IntID> + : SInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, DoubleRegs:$src1, + u5Imm:$src2), + !strconcat("$dst -= ", !strconcat(opc , "($src1, #$src2)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, DoubleRegs:$src1, + imm:$src2))], + "$dst2 = $dst">; + + +// +// MInst classes. +// + +class di_MInst_sisi_rnd_hh_s1<string opc, Intrinsic IntID> + : MInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , + "($src1.H, $src2.H):<<1:rnd")), + [(set DoubleRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class di_MInst_sisi_rnd_hh<string opc, Intrinsic IntID> + : MInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , + "($src1.H, $src2.H):rnd")), + [(set DoubleRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class di_MInst_sisi_rnd_hl_s1<string opc, Intrinsic IntID> + : MInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , + "($src1.H, $src2.L):<<1:rnd")), + [(set DoubleRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class di_MInst_sisi_rnd_hl<string opc, Intrinsic IntID> + : MInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , + "($src1.H, $src2.L):rnd")), + [(set DoubleRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class di_MInst_sisi_rnd_lh_s1<string opc, Intrinsic IntID> + : MInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , + "($src1.L, $src2.H):<<1:rnd")), + [(set DoubleRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class di_MInst_sisi_rnd_lh<string opc, Intrinsic IntID> + : MInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , + "($src1.L, $src2.H):rnd")), + [(set DoubleRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class di_MInst_sisi_rnd_ll_s1<string opc, Intrinsic IntID> + : MInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , + "($src1.L, $src2.L):<<1:rnd")), + [(set DoubleRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class di_MInst_sisi_rnd_ll<string opc, Intrinsic IntID> + : MInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , + "($src1.L, $src2.L):rnd")), + [(set DoubleRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class di_MInst_disisi_acc<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", !strconcat(opc , "($src1, $src2)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_disisi_nac<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , "($src1, $src2)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_disisi_acc_sat<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", !strconcat(opc , "($src1, $src2):sat")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_disisi_nac_sat<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , "($src1, $src2):sat")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_disisi_acc_sat_conj<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", !strconcat(opc , "($src1, $src2*):sat")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_disisi_nac_sat_conj<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , "($src1, $src2*):sat")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_disisi_nac_s1_sat<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , + "($src1, $src2):<<1:sat")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_disisi_acc_s1_sat_conj<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", !strconcat(opc , + "($src1, $src2*):<<1:sat")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_disisi_nac_s1_sat_conj<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , + "($src1, $src2*):<<1:sat")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_s8s8<string opc, Intrinsic IntID> + : MInst<(outs DoubleRegs:$dst), (ins s8Imm:$src1, s8Imm:$src2), + !strconcat("$dst = ", !strconcat(opc , "(#$src1, #$src2)")), + [(set DoubleRegs:$dst, (IntID imm:$src1, imm:$src2))]>; + +class si_MInst_sisi<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class di_MInst_sisi_hh<string opc, Intrinsic IntID> + : MInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.H, $src2.H)")), + [(set DoubleRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class di_MInst_sisi_hh_s1<string opc, Intrinsic IntID> + : MInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.H, $src2.H):<<1")), + [(set DoubleRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class di_MInst_sisi_lh<string opc, Intrinsic IntID> + : MInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.L, $src2.H)")), + [(set DoubleRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class di_MInst_sisi_lh_s1<string opc, Intrinsic IntID> + : MInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.L, $src2.H):<<1")), + [(set DoubleRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class di_MInst_sisi_hl<string opc, Intrinsic IntID> + : MInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.H, $src2.L)")), + [(set DoubleRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class di_MInst_sisi_hl_s1<string opc, Intrinsic IntID> + : MInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.H, $src2.L):<<1")), + [(set DoubleRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class di_MInst_sisi_ll<string opc, Intrinsic IntID> + : MInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.L, $src2.L)")), + [(set DoubleRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class di_MInst_sisi_ll_s1<string opc, Intrinsic IntID> + : MInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.L, $src2.L):<<1")), + [(set DoubleRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + + +class si_MInst_sisi_hh<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.H, $src2.H)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_hh_s1<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.H, $src2.H):<<1")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_lh<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.L, $src2.H)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_lh_s1<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.L, $src2.H):<<1")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_hl<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.H, $src2.L)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_hl_s1<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.H, $src2.L):<<1")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_ll<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.L, $src2.L)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_ll_s1<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.L, $src2.L):<<1")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_up<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class di_MInst_didi<string opc, Intrinsic IntID> + : MInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$src1, + DoubleRegs:$src2))]>; + +class di_MInst_didi_conj<string opc, Intrinsic IntID> + : MInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2*)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$src1, + DoubleRegs:$src2))]>; + +class di_MInst_sisi_s1_sat_conj<string opc, Intrinsic IntID> + : MInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , + "($src1, $src2*):<<1:sat")), + [(set DoubleRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class di_MInst_didi_s1_rnd_sat<string opc, Intrinsic IntID> + : MInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , + "($src1, $src2):<<1:rnd:sat")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$src1, + DoubleRegs:$src2))]>; + +class di_MInst_didi_sat<string opc, Intrinsic IntID> + : MInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2):sat")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$src1, + DoubleRegs:$src2))]>; + +class di_MInst_didi_rnd_sat<string opc, Intrinsic IntID> + : MInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , + "($src1, $src2):rnd:sat")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$src1, + DoubleRegs:$src2))]>; + +class si_SInst_sisi_sat<string opc, Intrinsic IntID> + : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2):sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_s1_rnd_sat<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , + "($src1, $src2):<<1:rnd:sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_l_s1_rnd_sat<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , + "($src1, $src2.L):<<1:rnd:sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_h_s1_rnd_sat<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , + "($src1, $src2.H):<<1:rnd:sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_rnd_sat_conj<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , + "($src1, $src2*):rnd:sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_s1_rnd_sat_conj<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , + "($src1, $src2*):<<1:rnd:sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_rnd_sat<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , + "($src1, $src2):rnd:sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_rnd<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2):rnd")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisisi_xacc<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src2, + IntRegs:$src3), + !strconcat("$dst ^= ", !strconcat(opc , "($src2, $src3)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src2, + IntRegs:$src3))], + "$dst2 = $dst">; + +class si_MInst_sisisi_acc<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src2, + IntRegs:$src3), + !strconcat("$dst += ", !strconcat(opc , "($src2, $src3)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src2, + IntRegs:$src3))], + "$dst2 = $dst">; + +class si_MInst_sisisi_nac<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src2, + IntRegs:$src3), + !strconcat("$dst -= ", !strconcat(opc , "($src2, $src3)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src2, + IntRegs:$src3))], + "$dst2 = $dst">; + +class si_MInst_sisis8_acc<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src2, + s8Imm:$src3), + !strconcat("$dst += ", !strconcat(opc , "($src2, #$src3)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src2, + imm:$src3))], + "$dst2 = $dst">; + +class si_MInst_sisis8_nac<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src2, + s8Imm:$src3), + !strconcat("$dst -= ", !strconcat(opc , "($src2, #$src3)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src2, + imm:$src3))], + "$dst2 = $dst">; + +class si_MInst_sisiu4u5<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + u4Imm:$src2, u5Imm:$src3), + !strconcat("$dst = ", !strconcat(opc , + "($src1, #$src2, #$src3)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + imm:$src2, imm:$src3))], + "$dst2 = $dst">; + +class si_MInst_sisiu8_acc<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src2, + u8Imm:$src3), + !strconcat("$dst += ", !strconcat(opc , "($src2, #$src3)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src2, + imm:$src3))], + "$dst2 = $dst">; + +class si_MInst_sisiu8_nac<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src2, + u8Imm:$src3), + !strconcat("$dst -= ", !strconcat(opc , "($src2, #$src3)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src2, + imm:$src3))], + "$dst2 = $dst">; + +class si_MInst_sisisi_acc_hh<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", !strconcat(opc , "($src1.H, $src2.H)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_acc_sat_lh<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", !strconcat(opc , + "($src1.L, $src2.H):sat")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_acc_sat_lh_s1<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", !strconcat(opc , + "($src1.L, $src2.H):<<1:sat")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_acc_sat_hh<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", !strconcat(opc , + "($src1.H, $src2.H):sat")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_acc_sat_hh_s1<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", !strconcat(opc , + "($src1.H, $src2.H):<<1:sat")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_acc_hh_s1<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", !strconcat(opc , + "($src1.H, $src2.H):<<1")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_nac_hh<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , "($src1.H, $src2.H)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_nac_sat_hh_s1<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , + "($src1.H, $src2.H):<<1:sat")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_nac_sat_hh<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , + "($src1.H, $src2.H):sat")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_nac_sat_hl_s1<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , + "($src1.H, $src2.L):<<1:sat")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_nac_sat_hl<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , + "($src1.H, $src2.L):sat")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_nac_sat_lh_s1<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , + "($src1.L, $src2.H):<<1:sat")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_nac_sat_lh<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , + "($src1.L, $src2.H):sat")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_nac_sat_ll_s1<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , + "($src1.L, $src2.L):<<1:sat")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_nac_sat_ll<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , + "($src1.L, $src2.L):sat")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_nac_hh_s1<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , + "($src1.H, $src2.H):<<1")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_acc_hl<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", !strconcat(opc , "($src1.H, $src2.L)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_acc_hl_s1<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", !strconcat(opc , + "($src1.H, $src2.L):<<1")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_nac_hl<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , "($src1.H, $src2.L)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_nac_hl_s1<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , + "($src1.H, $src2.L):<<1")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_acc_lh<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", !strconcat(opc , "($src1.L, $src2.H)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_acc_lh_s1<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", !strconcat(opc , + "($src1.L, $src2.H):<<1")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_nac_lh<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , "($src1.L, $src2.H)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_nac_lh_s1<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , + "($src1.L, $src2.H):<<1")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_acc_ll<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", !strconcat(opc , "($src1.L, $src2.L)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_acc_ll_s1<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", !strconcat(opc , + "($src1.L, $src2.L):<<1")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_acc_sat_ll_s1<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", !strconcat(opc , + "($src1.L, $src2.L):<<1:sat")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_acc_sat_hl_s1<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", !strconcat(opc , + "($src1.H, $src2.L):<<1:sat")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_acc_sat_ll<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", !strconcat(opc , + "($src1.L, $src2.L):sat")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_acc_sat_hl<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", !strconcat(opc , + "($src1.H, $src2.L):sat")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_nac_ll<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , "($src1.L, $src2.L)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_nac_ll_s1<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , + "($src1.L, $src2.L):<<1")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_nac_hh_sat<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , + "($src1.H, $src2.H):sat")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_nac_hh_s1_sat<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , + "($src1.H, $src2.H):<<1:sat")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_nac_hl_sat<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , + "($src1.H, $src2.L):sat")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_nac_hl_s1_sat<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , + "($src1.H, $src2.L):<<1:sat")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_nac_lh_sat<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , + "($src1.L, $src2.H):sat")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_nac_lh_s1_sat<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , + "($src1.L, $src2.H):<<1:sat")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_nac_ll_sat<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , + "($src1.L, $src2.L):sat")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_nac_ll_s1_sat<string opc, Intrinsic IntID> + : MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , + "($src1.L, $src2.L):<<1:sat")), + [(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_ALU32_sisi<string opc, Intrinsic IntID> + : ALU32_rr<(outs DoubleRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2)")), + [(set DoubleRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class di_MInst_sisi<string opc, Intrinsic IntID> + : MInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2)")), + [(set DoubleRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class di_MInst_sisi_sat<string opc, Intrinsic IntID> + : MInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2):sat")), + [(set DoubleRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class di_MInst_sisi_sat_conj<string opc, Intrinsic IntID> + : MInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2*):sat")), + [(set DoubleRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class di_MInst_sisi_s1_sat<string opc, Intrinsic IntID> + : MInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2):<<1:sat")), + [(set DoubleRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class di_MInst_didi_s1_sat<string opc, Intrinsic IntID> + : MInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2):<<1:sat")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$src1, + DoubleRegs:$src2))]>; + +class si_MInst_didi_s1_rnd_sat<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , + "($src1, $src2):<<1:rnd:sat")), + [(set IntRegs:$dst, (IntID DoubleRegs:$src1, DoubleRegs:$src2))]>; + +class si_MInst_didi_rnd_sat<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2):rnd:sat")), + [(set IntRegs:$dst, (IntID DoubleRegs:$src1, DoubleRegs:$src2))]>; + +class si_MInst_sisi_sat_hh<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.H, $src2.H):sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_sat_hh_s1<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , + "($src1.H, $src2.H):<<1:sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_sat_hl<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.H, $src2.L):sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_sat_hl_s1<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , + "($src1.H, $src2.L):<<1:sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_sat_lh<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.L, $src2.H):sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_sat_lh_s1<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , + "($src1.L, $src2.H):<<1:sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_sat_ll<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1.L, $src2.L):sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_sat_ll_s1<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , + "($src1.L, $src2.L):<<1:sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_sat_rnd_hh<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , + "($src1.H, $src2.H):rnd:sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_rnd_hh<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , + "($src1.H, $src2.H):rnd")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_rnd_hh_s1<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , + "($src1.H, $src2.H):<<1:rnd")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_sat_rnd_hh_s1<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", + !strconcat(opc , + "($src1.H, $src2.H):<<1:rnd:sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_rnd_hl<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", + !strconcat(opc , "($src1.H, $src2.L):rnd")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_rnd_hl_s1<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", + !strconcat(opc , "($src1.H, $src2.L):<<1:rnd")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_sat_rnd_hl<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", + !strconcat(opc , "($src1.H, $src2.L):rnd:sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_sat_rnd_hl_s1<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", + !strconcat(opc , "($src1.H, $src2.L):<<1:rnd:sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_rnd_lh<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", + !strconcat(opc , "($src1.L, $src2.H):rnd")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_sat_rnd_lh<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", + !strconcat(opc , "($src1.L, $src2.H):rnd:sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_sat_rnd_lh_s1<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", + !strconcat(opc , "($src1.L, $src2.H):<<1:rnd:sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_rnd_lh_s1<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", + !strconcat(opc , "($src1.L, $src2.H):<<1:rnd")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_sat_rnd_ll<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", + !strconcat(opc , "($src1.L, $src2.L):rnd:sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_sat_rnd_ll_s1<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", + !strconcat(opc , "($src1.L, $src2.L):<<1:rnd:sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_rnd_ll<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", + !strconcat(opc , "($src1.L, $src2.L):rnd")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_sisi_rnd_ll_s1<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", + !strconcat(opc , "($src1.L, $src2.L):<<1:rnd")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class di_MInst_dididi_acc_sat<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, + DoubleRegs:$src1, DoubleRegs:$src2), + !strconcat("$dst += ", !strconcat(opc , "($src1, $src2):sat")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, + DoubleRegs:$src1, + DoubleRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_dididi_acc_rnd_sat<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, DoubleRegs:$src1, + DoubleRegs:$src2), + !strconcat("$dst += ", + !strconcat(opc , "($src1, $src2):rnd:sat")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, + DoubleRegs:$src1, + DoubleRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_dididi_acc_s1_sat<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, + DoubleRegs:$src1, + DoubleRegs:$src2), + !strconcat("$dst += ", + !strconcat(opc , "($src1, $src2):<<1:sat")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, + DoubleRegs:$src1, + DoubleRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_dididi_acc_s1_rnd_sat<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, DoubleRegs:$src1, + DoubleRegs:$src2), + !strconcat("$dst += ", + !strconcat(opc , "($src1, $src2):<<1:rnd:sat")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, + DoubleRegs:$src1, + DoubleRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_dididi_acc<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, DoubleRegs:$src1, + DoubleRegs:$src2), + !strconcat("$dst += ", !strconcat(opc , "($src1, $src2)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, + DoubleRegs:$src1, + DoubleRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_dididi_acc_conj<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, DoubleRegs:$src1, + DoubleRegs:$src2), + !strconcat("$dst += ", !strconcat(opc , "($src1, $src2*)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, + DoubleRegs:$src1, + DoubleRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_disisi_acc_hh<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", !strconcat(opc , "($src1.H, $src2.H)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_disisi_acc_hl<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", !strconcat(opc , "($src1.H, $src2.L)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_disisi_acc_lh<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", !strconcat(opc , "($src1.L, $src2.H)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_disisi_acc_ll<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", !strconcat(opc , "($src1.L, $src2.L)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_disisi_acc_hh_s1<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", + !strconcat(opc , "($src1.H, $src2.H):<<1")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_disisi_acc_hl_s1<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", + !strconcat(opc , "($src1.H, $src2.L):<<1")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_disisi_acc_lh_s1<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", + !strconcat(opc , "($src1.L, $src2.H):<<1")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_disisi_acc_ll_s1<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", + !strconcat(opc , "($src1.L, $src2.L):<<1")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_disisi_nac_hh<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , "($src1.H, $src2.H)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_disisi_nac_hl<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , "($src1.H, $src2.L)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_disisi_nac_lh<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , "($src1.L, $src2.H)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_disisi_nac_ll<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", !strconcat(opc , "($src1.L, $src2.L)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_disisi_nac_hh_s1<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", + !strconcat(opc , "($src1.H, $src2.H):<<1")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_disisi_nac_hl_s1<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", + !strconcat(opc , "($src1.H, $src2.L):<<1")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_disisi_nac_lh_s1<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", + !strconcat(opc , "($src1.L, $src2.H):<<1")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_disisi_nac_ll_s1<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst -= ", + !strconcat(opc , "($src1.L, $src2.L):<<1")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_disisi_acc_s1_sat<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", + !strconcat(opc , "($src1, $src2):<<1:sat")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, IntRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class di_MInst_disi_s1_sat<string opc, Intrinsic IntID> + : MInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2):<<1:sat")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$src1, IntRegs:$src2))]>; + +class di_MInst_didisi_acc_s1_sat<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, DoubleRegs:$src1, + IntRegs:$src2), + !strconcat("$dst += ", + !strconcat(opc , "($src1, $src2):<<1:sat")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, + DoubleRegs:$src1, + IntRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_disi_s1_rnd_sat<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins DoubleRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", + !strconcat(opc , "($src1, $src2):<<1:rnd:sat")), + [(set IntRegs:$dst, (IntID DoubleRegs:$src1, IntRegs:$src2))]>; + +class si_MInst_didi<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, $src2)")), + [(set IntRegs:$dst, (IntID DoubleRegs:$src1, DoubleRegs:$src2))]>; + + +/******************************************************************** +* ALU32/ALU * +*********************************************************************/ + +// ALU32 / ALU / Add. +def Hexagon_A2_add: + si_ALU32_sisi <"add", int_hexagon_A2_add>; +def Hexagon_A2_addi: + si_ALU32_sis16 <"add", int_hexagon_A2_addi>; + +// ALU32 / ALU / Logical operations. +def Hexagon_A2_and: + si_ALU32_sisi <"and", int_hexagon_A2_and>; +def Hexagon_A2_andir: + si_ALU32_sis10 <"and", int_hexagon_A2_andir>; +def Hexagon_A2_not: + si_ALU32_si <"not", int_hexagon_A2_not>; +def Hexagon_A2_or: + si_ALU32_sisi <"or", int_hexagon_A2_or>; +def Hexagon_A2_orir: + si_ALU32_sis10 <"or", int_hexagon_A2_orir>; +def Hexagon_A2_xor: + si_ALU32_sisi <"xor", int_hexagon_A2_xor>; + +// ALU32 / ALU / Negate. +def Hexagon_A2_neg: + si_ALU32_si <"neg", int_hexagon_A2_neg>; + +// ALU32 / ALU / Subtract. +def Hexagon_A2_sub: + si_ALU32_sisi <"sub", int_hexagon_A2_sub>; +def Hexagon_A2_subri: + si_ALU32_s10si <"sub", int_hexagon_A2_subri>; + +// ALU32 / ALU / Transfer Immediate. +def Hexagon_A2_tfril: + si_lo_ALU32_siu16 <"", int_hexagon_A2_tfril>; +def Hexagon_A2_tfrih: + si_hi_ALU32_siu16 <"", int_hexagon_A2_tfrih>; +def Hexagon_A2_tfrsi: + si_ALU32_s16 <"", int_hexagon_A2_tfrsi>; +def Hexagon_A2_tfrpi: + di_ALU32_s8 <"", int_hexagon_A2_tfrpi>; + +// ALU32 / ALU / Transfer Register. +def Hexagon_A2_tfr: + si_ALU32_si_tfr <"", int_hexagon_A2_tfr>; + +/******************************************************************** +* ALU32/PERM * +*********************************************************************/ + +// ALU32 / PERM / Combine. +def Hexagon_A2_combinew: + di_ALU32_sisi <"combine", int_hexagon_A2_combinew>; +def Hexagon_A2_combine_hh: + si_MInst_sisi_hh <"combine", int_hexagon_A2_combine_hh>; +def Hexagon_A2_combine_lh: + si_MInst_sisi_lh <"combine", int_hexagon_A2_combine_lh>; +def Hexagon_A2_combine_hl: + si_MInst_sisi_hl <"combine", int_hexagon_A2_combine_hl>; +def Hexagon_A2_combine_ll: + si_MInst_sisi_ll <"combine", int_hexagon_A2_combine_ll>; +def Hexagon_A2_combineii: + di_MInst_s8s8 <"combine", int_hexagon_A2_combineii>; + +// ALU32 / PERM / Mux. +def Hexagon_C2_mux: + si_ALU32_qisisi <"mux", int_hexagon_C2_mux>; +def Hexagon_C2_muxri: + si_ALU32_qis8si <"mux", int_hexagon_C2_muxri>; +def Hexagon_C2_muxir: + si_ALU32_qisis8 <"mux", int_hexagon_C2_muxir>; +def Hexagon_C2_muxii: + si_ALU32_qis8s8 <"mux", int_hexagon_C2_muxii>; + +// ALU32 / PERM / Shift halfword. +def Hexagon_A2_aslh: + si_ALU32_si <"aslh", int_hexagon_A2_aslh>; +def Hexagon_A2_asrh: + si_ALU32_si <"asrh", int_hexagon_A2_asrh>; +def SI_to_SXTHI_asrh: + si_ALU32_si <"asrh", int_hexagon_SI_to_SXTHI_asrh>; + +// ALU32 / PERM / Sign/zero extend. +def Hexagon_A2_sxth: + si_ALU32_si <"sxth", int_hexagon_A2_sxth>; +def Hexagon_A2_sxtb: + si_ALU32_si <"sxtb", int_hexagon_A2_sxtb>; +def Hexagon_A2_zxth: + si_ALU32_si <"zxth", int_hexagon_A2_zxth>; +def Hexagon_A2_zxtb: + si_ALU32_si <"zxtb", int_hexagon_A2_zxtb>; + +/******************************************************************** +* ALU32/PRED * +*********************************************************************/ + +// ALU32 / PRED / Compare. +def Hexagon_C2_cmpeq: + qi_ALU32_sisi <"cmp.eq", int_hexagon_C2_cmpeq>; +def Hexagon_C2_cmpeqi: + qi_ALU32_sis10 <"cmp.eq", int_hexagon_C2_cmpeqi>; +def Hexagon_C2_cmpgei: + qi_ALU32_sis8 <"cmp.ge", int_hexagon_C2_cmpgei>; +def Hexagon_C2_cmpgeui: + qi_ALU32_siu8 <"cmp.geu", int_hexagon_C2_cmpgeui>; +def Hexagon_C2_cmpgt: + qi_ALU32_sisi <"cmp.gt", int_hexagon_C2_cmpgt>; +def Hexagon_C2_cmpgti: + qi_ALU32_sis10 <"cmp.gt", int_hexagon_C2_cmpgti>; +def Hexagon_C2_cmpgtu: + qi_ALU32_sisi <"cmp.gtu", int_hexagon_C2_cmpgtu>; +def Hexagon_C2_cmpgtui: + qi_ALU32_siu9 <"cmp.gtu", int_hexagon_C2_cmpgtui>; +def Hexagon_C2_cmplt: + qi_ALU32_sisi <"cmp.lt", int_hexagon_C2_cmplt>; +def Hexagon_C2_cmpltu: + qi_ALU32_sisi <"cmp.ltu", int_hexagon_C2_cmpltu>; + +/******************************************************************** +* ALU32/VH * +*********************************************************************/ + +// ALU32 / VH / Vector add halfwords. +// Rd32=vadd[u]h(Rs32,Rt32:sat] +def Hexagon_A2_svaddh: + si_ALU32_sisi <"vaddh", int_hexagon_A2_svaddh>; +def Hexagon_A2_svaddhs: + si_ALU32_sisi_sat <"vaddh", int_hexagon_A2_svaddhs>; +def Hexagon_A2_svadduhs: + si_ALU32_sisi_sat <"vadduh", int_hexagon_A2_svadduhs>; + +// ALU32 / VH / Vector average halfwords. +def Hexagon_A2_svavgh: + si_ALU32_sisi <"vavgh", int_hexagon_A2_svavgh>; +def Hexagon_A2_svavghs: + si_ALU32_sisi_rnd <"vavgh", int_hexagon_A2_svavghs>; +def Hexagon_A2_svnavgh: + si_ALU32_sisi <"vnavgh", int_hexagon_A2_svnavgh>; + +// ALU32 / VH / Vector subtract halfwords. +def Hexagon_A2_svsubh: + si_ALU32_sisi <"vsubh", int_hexagon_A2_svsubh>; +def Hexagon_A2_svsubhs: + si_ALU32_sisi_sat <"vsubh", int_hexagon_A2_svsubhs>; +def Hexagon_A2_svsubuhs: + si_ALU32_sisi_sat <"vsubuh", int_hexagon_A2_svsubuhs>; + +/******************************************************************** +* ALU64/ALU * +*********************************************************************/ + +// ALU64 / ALU / Add. +def Hexagon_A2_addp: + di_ALU64_didi <"add", int_hexagon_A2_addp>; +def Hexagon_A2_addsat: + si_ALU64_sisi_sat <"add", int_hexagon_A2_addsat>; + +// ALU64 / ALU / Add halfword. +// Even though the definition says hl, it should be lh - +//so DON'T change the class " si_ALU64_sisi_l16_lh " it inherits. +def Hexagon_A2_addh_l16_hl: + si_ALU64_sisi_l16_lh <"add", int_hexagon_A2_addh_l16_hl>; +def Hexagon_A2_addh_l16_ll: + si_ALU64_sisi_l16_ll <"add", int_hexagon_A2_addh_l16_ll>; + +def Hexagon_A2_addh_l16_sat_hl: + si_ALU64_sisi_l16_sat_lh <"add", int_hexagon_A2_addh_l16_sat_hl>; +def Hexagon_A2_addh_l16_sat_ll: + si_ALU64_sisi_l16_sat_ll <"add", int_hexagon_A2_addh_l16_sat_ll>; + +def Hexagon_A2_addh_h16_hh: + si_ALU64_sisi_h16_hh <"add", int_hexagon_A2_addh_h16_hh>; +def Hexagon_A2_addh_h16_hl: + si_ALU64_sisi_h16_hl <"add", int_hexagon_A2_addh_h16_hl>; +def Hexagon_A2_addh_h16_lh: + si_ALU64_sisi_h16_lh <"add", int_hexagon_A2_addh_h16_lh>; +def Hexagon_A2_addh_h16_ll: + si_ALU64_sisi_h16_ll <"add", int_hexagon_A2_addh_h16_ll>; + +def Hexagon_A2_addh_h16_sat_hh: + si_ALU64_sisi_h16_sat_hh <"add", int_hexagon_A2_addh_h16_sat_hh>; +def Hexagon_A2_addh_h16_sat_hl: + si_ALU64_sisi_h16_sat_hl <"add", int_hexagon_A2_addh_h16_sat_hl>; +def Hexagon_A2_addh_h16_sat_lh: + si_ALU64_sisi_h16_sat_lh <"add", int_hexagon_A2_addh_h16_sat_lh>; +def Hexagon_A2_addh_h16_sat_ll: + si_ALU64_sisi_h16_sat_ll <"add", int_hexagon_A2_addh_h16_sat_ll>; + +// ALU64 / ALU / Compare. +def Hexagon_C2_cmpeqp: + qi_ALU64_didi <"cmp.eq", int_hexagon_C2_cmpeqp>; +def Hexagon_C2_cmpgtp: + qi_ALU64_didi <"cmp.gt", int_hexagon_C2_cmpgtp>; +def Hexagon_C2_cmpgtup: + qi_ALU64_didi <"cmp.gtu", int_hexagon_C2_cmpgtup>; + +// ALU64 / ALU / Logical operations. +def Hexagon_A2_andp: + di_ALU64_didi <"and", int_hexagon_A2_andp>; +def Hexagon_A2_orp: + di_ALU64_didi <"or", int_hexagon_A2_orp>; +def Hexagon_A2_xorp: + di_ALU64_didi <"xor", int_hexagon_A2_xorp>; + +// ALU64 / ALU / Maximum. +def Hexagon_A2_max: + si_ALU64_sisi <"max", int_hexagon_A2_max>; +def Hexagon_A2_maxu: + si_ALU64_sisi <"maxu", int_hexagon_A2_maxu>; + +// ALU64 / ALU / Minimum. +def Hexagon_A2_min: + si_ALU64_sisi <"min", int_hexagon_A2_min>; +def Hexagon_A2_minu: + si_ALU64_sisi <"minu", int_hexagon_A2_minu>; + +// ALU64 / ALU / Subtract. +def Hexagon_A2_subp: + di_ALU64_didi <"sub", int_hexagon_A2_subp>; +def Hexagon_A2_subsat: + si_ALU64_sisi_sat <"sub", int_hexagon_A2_subsat>; + +// ALU64 / ALU / Subtract halfword. +// Even though the definition says hl, it should be lh - +//so DON'T change the class " si_ALU64_sisi_l16_lh " it inherits. +def Hexagon_A2_subh_l16_hl: + si_ALU64_sisi_l16_lh <"sub", int_hexagon_A2_subh_l16_hl>; +def Hexagon_A2_subh_l16_ll: + si_ALU64_sisi_l16_ll <"sub", int_hexagon_A2_subh_l16_ll>; + +def Hexagon_A2_subh_l16_sat_hl: + si_ALU64_sisi_l16_sat_lh <"sub", int_hexagon_A2_subh_l16_sat_hl>; +def Hexagon_A2_subh_l16_sat_ll: + si_ALU64_sisi_l16_sat_ll <"sub", int_hexagon_A2_subh_l16_sat_ll>; + +def Hexagon_A2_subh_h16_hh: + si_ALU64_sisi_h16_hh <"sub", int_hexagon_A2_subh_h16_hh>; +def Hexagon_A2_subh_h16_hl: + si_ALU64_sisi_h16_hl <"sub", int_hexagon_A2_subh_h16_hl>; +def Hexagon_A2_subh_h16_lh: + si_ALU64_sisi_h16_lh <"sub", int_hexagon_A2_subh_h16_lh>; +def Hexagon_A2_subh_h16_ll: + si_ALU64_sisi_h16_ll <"sub", int_hexagon_A2_subh_h16_ll>; + +def Hexagon_A2_subh_h16_sat_hh: + si_ALU64_sisi_h16_sat_hh <"sub", int_hexagon_A2_subh_h16_sat_hh>; +def Hexagon_A2_subh_h16_sat_hl: + si_ALU64_sisi_h16_sat_hl <"sub", int_hexagon_A2_subh_h16_sat_hl>; +def Hexagon_A2_subh_h16_sat_lh: + si_ALU64_sisi_h16_sat_lh <"sub", int_hexagon_A2_subh_h16_sat_lh>; +def Hexagon_A2_subh_h16_sat_ll: + si_ALU64_sisi_h16_sat_ll <"sub", int_hexagon_A2_subh_h16_sat_ll>; + +// ALU64 / ALU / Transfer register. +def Hexagon_A2_tfrp: + di_ALU64_di <"", int_hexagon_A2_tfrp>; + +/******************************************************************** +* ALU64/BIT * +*********************************************************************/ + +// ALU64 / BIT / Masked parity. +def Hexagon_S2_parityp: + si_ALU64_didi <"parity", int_hexagon_S2_parityp>; + +/******************************************************************** +* ALU64/PERM * +*********************************************************************/ + +// ALU64 / PERM / Vector pack high and low halfwords. +def Hexagon_S2_packhl: + di_ALU64_sisi <"packhl", int_hexagon_S2_packhl>; + +/******************************************************************** +* ALU64/VB * +*********************************************************************/ + +// ALU64 / VB / Vector add unsigned bytes. +def Hexagon_A2_vaddub: + di_ALU64_didi <"vaddub", int_hexagon_A2_vaddub>; +def Hexagon_A2_vaddubs: + di_ALU64_didi_sat <"vaddub", int_hexagon_A2_vaddubs>; + +// ALU64 / VB / Vector average unsigned bytes. +def Hexagon_A2_vavgub: + di_ALU64_didi <"vavgub", int_hexagon_A2_vavgub>; +def Hexagon_A2_vavgubr: + di_ALU64_didi_rnd <"vavgub", int_hexagon_A2_vavgubr>; + +// ALU64 / VB / Vector compare unsigned bytes. +def Hexagon_A2_vcmpbeq: + qi_ALU64_didi <"vcmpb.eq", int_hexagon_A2_vcmpbeq>; +def Hexagon_A2_vcmpbgtu: + qi_ALU64_didi <"vcmpb.gtu",int_hexagon_A2_vcmpbgtu>; + +// ALU64 / VB / Vector maximum/minimum unsigned bytes. +def Hexagon_A2_vmaxub: + di_ALU64_didi <"vmaxub", int_hexagon_A2_vmaxub>; +def Hexagon_A2_vminub: + di_ALU64_didi <"vminub", int_hexagon_A2_vminub>; + +// ALU64 / VB / Vector subtract unsigned bytes. +def Hexagon_A2_vsubub: + di_ALU64_didi <"vsubub", int_hexagon_A2_vsubub>; +def Hexagon_A2_vsububs: + di_ALU64_didi_sat <"vsubub", int_hexagon_A2_vsububs>; + +// ALU64 / VB / Vector mux. +def Hexagon_C2_vmux: + di_ALU64_qididi <"vmux", int_hexagon_C2_vmux>; + + +/******************************************************************** +* ALU64/VH * +*********************************************************************/ + +// ALU64 / VH / Vector add halfwords. +// Rdd64=vadd[u]h(Rss64,Rtt64:sat] +def Hexagon_A2_vaddh: + di_ALU64_didi <"vaddh", int_hexagon_A2_vaddh>; +def Hexagon_A2_vaddhs: + di_ALU64_didi_sat <"vaddh", int_hexagon_A2_vaddhs>; +def Hexagon_A2_vadduhs: + di_ALU64_didi_sat <"vadduh", int_hexagon_A2_vadduhs>; + +// ALU64 / VH / Vector average halfwords. +// Rdd64=v[n]avg[u]h(Rss64,Rtt64:rnd/:crnd][:sat] +def Hexagon_A2_vavgh: + di_ALU64_didi <"vavgh", int_hexagon_A2_vavgh>; +def Hexagon_A2_vavghcr: + di_ALU64_didi_crnd <"vavgh", int_hexagon_A2_vavghcr>; +def Hexagon_A2_vavghr: + di_ALU64_didi_rnd <"vavgh", int_hexagon_A2_vavghr>; +def Hexagon_A2_vavguh: + di_ALU64_didi <"vavguh", int_hexagon_A2_vavguh>; +def Hexagon_A2_vavguhr: + di_ALU64_didi_rnd <"vavguh", int_hexagon_A2_vavguhr>; +def Hexagon_A2_vnavgh: + di_ALU64_didi <"vnavgh", int_hexagon_A2_vnavgh>; +def Hexagon_A2_vnavghcr: + di_ALU64_didi_crnd_sat <"vnavgh", int_hexagon_A2_vnavghcr>; +def Hexagon_A2_vnavghr: + di_ALU64_didi_rnd_sat <"vnavgh", int_hexagon_A2_vnavghr>; + +// ALU64 / VH / Vector compare halfwords. +def Hexagon_A2_vcmpheq: + qi_ALU64_didi <"vcmph.eq", int_hexagon_A2_vcmpheq>; +def Hexagon_A2_vcmphgt: + qi_ALU64_didi <"vcmph.gt", int_hexagon_A2_vcmphgt>; +def Hexagon_A2_vcmphgtu: + qi_ALU64_didi <"vcmph.gtu",int_hexagon_A2_vcmphgtu>; + +// ALU64 / VH / Vector maximum halfwords. +def Hexagon_A2_vmaxh: + di_ALU64_didi <"vmaxh", int_hexagon_A2_vmaxh>; +def Hexagon_A2_vmaxuh: + di_ALU64_didi <"vmaxuh", int_hexagon_A2_vmaxuh>; + +// ALU64 / VH / Vector minimum halfwords. +def Hexagon_A2_vminh: + di_ALU64_didi <"vminh", int_hexagon_A2_vminh>; +def Hexagon_A2_vminuh: + di_ALU64_didi <"vminuh", int_hexagon_A2_vminuh>; + +// ALU64 / VH / Vector subtract halfwords. +def Hexagon_A2_vsubh: + di_ALU64_didi <"vsubh", int_hexagon_A2_vsubh>; +def Hexagon_A2_vsubhs: + di_ALU64_didi_sat <"vsubh", int_hexagon_A2_vsubhs>; +def Hexagon_A2_vsubuhs: + di_ALU64_didi_sat <"vsubuh", int_hexagon_A2_vsubuhs>; + + +/******************************************************************** +* ALU64/VW * +*********************************************************************/ + +// ALU64 / VW / Vector add words. +// Rdd32=vaddw(Rss32,Rtt32)[:sat] +def Hexagon_A2_vaddw: + di_ALU64_didi <"vaddw", int_hexagon_A2_vaddw>; +def Hexagon_A2_vaddws: + di_ALU64_didi_sat <"vaddw", int_hexagon_A2_vaddws>; + +// ALU64 / VW / Vector average words. +def Hexagon_A2_vavguw: + di_ALU64_didi <"vavguw", int_hexagon_A2_vavguw>; +def Hexagon_A2_vavguwr: + di_ALU64_didi_rnd <"vavguw", int_hexagon_A2_vavguwr>; +def Hexagon_A2_vavgw: + di_ALU64_didi <"vavgw", int_hexagon_A2_vavgw>; +def Hexagon_A2_vavgwcr: + di_ALU64_didi_crnd <"vavgw", int_hexagon_A2_vavgwcr>; +def Hexagon_A2_vavgwr: + di_ALU64_didi_rnd <"vavgw", int_hexagon_A2_vavgwr>; +def Hexagon_A2_vnavgw: + di_ALU64_didi <"vnavgw", int_hexagon_A2_vnavgw>; +def Hexagon_A2_vnavgwcr: + di_ALU64_didi_crnd_sat <"vnavgw", int_hexagon_A2_vnavgwcr>; +def Hexagon_A2_vnavgwr: + di_ALU64_didi_rnd_sat <"vnavgw", int_hexagon_A2_vnavgwr>; + +// ALU64 / VW / Vector compare words. +def Hexagon_A2_vcmpweq: + qi_ALU64_didi <"vcmpw.eq", int_hexagon_A2_vcmpweq>; +def Hexagon_A2_vcmpwgt: + qi_ALU64_didi <"vcmpw.gt", int_hexagon_A2_vcmpwgt>; +def Hexagon_A2_vcmpwgtu: + qi_ALU64_didi <"vcmpw.gtu",int_hexagon_A2_vcmpwgtu>; + +// ALU64 / VW / Vector maximum words. +def Hexagon_A2_vmaxw: + di_ALU64_didi <"vmaxw", int_hexagon_A2_vmaxw>; +def Hexagon_A2_vmaxuw: + di_ALU64_didi <"vmaxuw", int_hexagon_A2_vmaxuw>; + +// ALU64 / VW / Vector minimum words. +def Hexagon_A2_vminw: + di_ALU64_didi <"vminw", int_hexagon_A2_vminw>; +def Hexagon_A2_vminuw: + di_ALU64_didi <"vminuw", int_hexagon_A2_vminuw>; + +// ALU64 / VW / Vector subtract words. +def Hexagon_A2_vsubw: + di_ALU64_didi <"vsubw", int_hexagon_A2_vsubw>; +def Hexagon_A2_vsubws: + di_ALU64_didi_sat <"vsubw", int_hexagon_A2_vsubws>; + + +/******************************************************************** +* CR * +*********************************************************************/ + +// CR / Logical reductions on predicates. +def Hexagon_C2_all8: + qi_SInst_qi <"all8", int_hexagon_C2_all8>; +def Hexagon_C2_any8: + qi_SInst_qi <"any8", int_hexagon_C2_any8>; + +// CR / Logical operations on predicates. +def Hexagon_C2_pxfer_map: + qi_SInst_qi_pxfer <"", int_hexagon_C2_pxfer_map>; +def Hexagon_C2_and: + qi_SInst_qiqi <"and", int_hexagon_C2_and>; +def Hexagon_C2_andn: + qi_SInst_qiqi_neg <"and", int_hexagon_C2_andn>; +def Hexagon_C2_not: + qi_SInst_qi <"not", int_hexagon_C2_not>; +def Hexagon_C2_or: + qi_SInst_qiqi <"or", int_hexagon_C2_or>; +def Hexagon_C2_orn: + qi_SInst_qiqi_neg <"or", int_hexagon_C2_orn>; +def Hexagon_C2_xor: + qi_SInst_qiqi <"xor", int_hexagon_C2_xor>; + + +/******************************************************************** +* MTYPE/ALU * +*********************************************************************/ + +// MTYPE / ALU / Add and accumulate. +def Hexagon_M2_acci: + si_MInst_sisisi_acc <"add", int_hexagon_M2_acci>; +def Hexagon_M2_accii: + si_MInst_sisis8_acc <"add", int_hexagon_M2_accii>; +def Hexagon_M2_nacci: + si_MInst_sisisi_nac <"add", int_hexagon_M2_nacci>; +def Hexagon_M2_naccii: + si_MInst_sisis8_nac <"add", int_hexagon_M2_naccii>; + +// MTYPE / ALU / Subtract and accumulate. +def Hexagon_M2_subacc: + si_MInst_sisisi_acc <"sub", int_hexagon_M2_subacc>; + +// MTYPE / ALU / Vector absolute difference. +def Hexagon_M2_vabsdiffh: + di_MInst_didi <"vabsdiffh",int_hexagon_M2_vabsdiffh>; +def Hexagon_M2_vabsdiffw: + di_MInst_didi <"vabsdiffw",int_hexagon_M2_vabsdiffw>; + +// MTYPE / ALU / XOR and xor with destination. +def Hexagon_M2_xor_xacc: + si_MInst_sisisi_xacc <"xor", int_hexagon_M2_xor_xacc>; + + +/******************************************************************** +* MTYPE/COMPLEX * +*********************************************************************/ + +// MTYPE / COMPLEX / Complex multiply. +// Rdd[-+]=cmpy(Rs, Rt:<<1]:sat +def Hexagon_M2_cmpys_s1: + di_MInst_sisi_s1_sat <"cmpy", int_hexagon_M2_cmpys_s1>; +def Hexagon_M2_cmpys_s0: + di_MInst_sisi_sat <"cmpy", int_hexagon_M2_cmpys_s0>; +def Hexagon_M2_cmpysc_s1: + di_MInst_sisi_s1_sat_conj <"cmpy", int_hexagon_M2_cmpysc_s1>; +def Hexagon_M2_cmpysc_s0: + di_MInst_sisi_sat_conj <"cmpy", int_hexagon_M2_cmpysc_s0>; + +def Hexagon_M2_cmacs_s1: + di_MInst_disisi_acc_s1_sat <"cmpy", int_hexagon_M2_cmacs_s1>; +def Hexagon_M2_cmacs_s0: + di_MInst_disisi_acc_sat <"cmpy", int_hexagon_M2_cmacs_s0>; +def Hexagon_M2_cmacsc_s1: + di_MInst_disisi_acc_s1_sat_conj <"cmpy", int_hexagon_M2_cmacsc_s1>; +def Hexagon_M2_cmacsc_s0: + di_MInst_disisi_acc_sat_conj <"cmpy", int_hexagon_M2_cmacsc_s0>; + +def Hexagon_M2_cnacs_s1: + di_MInst_disisi_nac_s1_sat <"cmpy", int_hexagon_M2_cnacs_s1>; +def Hexagon_M2_cnacs_s0: + di_MInst_disisi_nac_sat <"cmpy", int_hexagon_M2_cnacs_s0>; +def Hexagon_M2_cnacsc_s1: + di_MInst_disisi_nac_s1_sat_conj <"cmpy", int_hexagon_M2_cnacsc_s1>; +def Hexagon_M2_cnacsc_s0: + di_MInst_disisi_nac_sat_conj <"cmpy", int_hexagon_M2_cnacsc_s0>; + +// MTYPE / COMPLEX / Complex multiply real or imaginary. +def Hexagon_M2_cmpyr_s0: + di_MInst_sisi <"cmpyr", int_hexagon_M2_cmpyr_s0>; +def Hexagon_M2_cmacr_s0: + di_MInst_disisi_acc <"cmpyr", int_hexagon_M2_cmacr_s0>; + +def Hexagon_M2_cmpyi_s0: + di_MInst_sisi <"cmpyi", int_hexagon_M2_cmpyi_s0>; +def Hexagon_M2_cmaci_s0: + di_MInst_disisi_acc <"cmpyi", int_hexagon_M2_cmaci_s0>; + +// MTYPE / COMPLEX / Complex multiply with round and pack. +// Rxx32+=cmpy(Rs32,[*]Rt32:<<1]:rnd:sat +def Hexagon_M2_cmpyrs_s0: + si_MInst_sisi_rnd_sat <"cmpy", int_hexagon_M2_cmpyrs_s0>; +def Hexagon_M2_cmpyrs_s1: + si_MInst_sisi_s1_rnd_sat <"cmpy", int_hexagon_M2_cmpyrs_s1>; + +def Hexagon_M2_cmpyrsc_s0: + si_MInst_sisi_rnd_sat_conj <"cmpy", int_hexagon_M2_cmpyrsc_s0>; +def Hexagon_M2_cmpyrsc_s1: + si_MInst_sisi_s1_rnd_sat_conj <"cmpy", int_hexagon_M2_cmpyrsc_s1>; + +//MTYPE / COMPLEX / Vector complex multiply real or imaginary. +def Hexagon_M2_vcmpy_s0_sat_i: + di_MInst_didi_sat <"vcmpyi", int_hexagon_M2_vcmpy_s0_sat_i>; +def Hexagon_M2_vcmpy_s1_sat_i: + di_MInst_didi_s1_sat <"vcmpyi", int_hexagon_M2_vcmpy_s1_sat_i>; + +def Hexagon_M2_vcmpy_s0_sat_r: + di_MInst_didi_sat <"vcmpyr", int_hexagon_M2_vcmpy_s0_sat_r>; +def Hexagon_M2_vcmpy_s1_sat_r: + di_MInst_didi_s1_sat <"vcmpyr", int_hexagon_M2_vcmpy_s1_sat_r>; + +def Hexagon_M2_vcmac_s0_sat_i: + di_MInst_dididi_acc_sat <"vcmpyi", int_hexagon_M2_vcmac_s0_sat_i>; +def Hexagon_M2_vcmac_s0_sat_r: + di_MInst_dididi_acc_sat <"vcmpyr", int_hexagon_M2_vcmac_s0_sat_r>; + +//MTYPE / COMPLEX / Vector reduce complex multiply real or imaginary. +def Hexagon_M2_vrcmpyi_s0: + di_MInst_didi <"vrcmpyi", int_hexagon_M2_vrcmpyi_s0>; +def Hexagon_M2_vrcmpyr_s0: + di_MInst_didi <"vrcmpyr", int_hexagon_M2_vrcmpyr_s0>; + +def Hexagon_M2_vrcmpyi_s0c: + di_MInst_didi_conj <"vrcmpyi", int_hexagon_M2_vrcmpyi_s0c>; +def Hexagon_M2_vrcmpyr_s0c: + di_MInst_didi_conj <"vrcmpyr", int_hexagon_M2_vrcmpyr_s0c>; + +def Hexagon_M2_vrcmaci_s0: + di_MInst_dididi_acc <"vrcmpyi", int_hexagon_M2_vrcmaci_s0>; +def Hexagon_M2_vrcmacr_s0: + di_MInst_dididi_acc <"vrcmpyr", int_hexagon_M2_vrcmacr_s0>; + +def Hexagon_M2_vrcmaci_s0c: + di_MInst_dididi_acc_conj <"vrcmpyi", int_hexagon_M2_vrcmaci_s0c>; +def Hexagon_M2_vrcmacr_s0c: + di_MInst_dididi_acc_conj <"vrcmpyr", int_hexagon_M2_vrcmacr_s0c>; + + +/******************************************************************** +* MTYPE/MPYH * +*********************************************************************/ + +// MTYPE / MPYH / Multiply and use lower result. +//def Hexagon_M2_mpysmi: +// si_MInst_sim9 <"mpyi", int_hexagon_M2_mpysmi>; +def Hexagon_M2_mpyi: + si_MInst_sisi <"mpyi", int_hexagon_M2_mpyi>; +def Hexagon_M2_mpyui: + si_MInst_sisi <"mpyui", int_hexagon_M2_mpyui>; +def Hexagon_M2_macsip: + si_MInst_sisiu8_acc <"mpyi", int_hexagon_M2_macsip>; +def Hexagon_M2_maci: + si_MInst_sisisi_acc <"mpyi", int_hexagon_M2_maci>; +def Hexagon_M2_macsin: + si_MInst_sisiu8_nac <"mpyi", int_hexagon_M2_macsin>; + +// MTYPE / MPYH / Multiply word by half (32x16). +//Rdd[+]=vmpywoh(Rss,Rtt)[:<<1][:rnd][:sat] +//Rdd[+]=vmpyweh(Rss,Rtt)[:<<1][:rnd][:sat] +def Hexagon_M2_mmpyl_rs1: + di_MInst_didi_s1_rnd_sat <"vmpyweh", int_hexagon_M2_mmpyl_rs1>; +def Hexagon_M2_mmpyl_s1: + di_MInst_didi_s1_sat <"vmpyweh", int_hexagon_M2_mmpyl_s1>; +def Hexagon_M2_mmpyl_rs0: + di_MInst_didi_rnd_sat <"vmpyweh", int_hexagon_M2_mmpyl_rs0>; +def Hexagon_M2_mmpyl_s0: + di_MInst_didi_sat <"vmpyweh", int_hexagon_M2_mmpyl_s0>; +def Hexagon_M2_mmpyh_rs1: + di_MInst_didi_s1_rnd_sat <"vmpywoh", int_hexagon_M2_mmpyh_rs1>; +def Hexagon_M2_mmpyh_s1: + di_MInst_didi_s1_sat <"vmpywoh", int_hexagon_M2_mmpyh_s1>; +def Hexagon_M2_mmpyh_rs0: + di_MInst_didi_rnd_sat <"vmpywoh", int_hexagon_M2_mmpyh_rs0>; +def Hexagon_M2_mmpyh_s0: + di_MInst_didi_sat <"vmpywoh", int_hexagon_M2_mmpyh_s0>; +def Hexagon_M2_mmacls_rs1: + di_MInst_dididi_acc_s1_rnd_sat <"vmpyweh", int_hexagon_M2_mmacls_rs1>; +def Hexagon_M2_mmacls_s1: + di_MInst_dididi_acc_s1_sat <"vmpyweh", int_hexagon_M2_mmacls_s1>; +def Hexagon_M2_mmacls_rs0: + di_MInst_dididi_acc_rnd_sat <"vmpyweh", int_hexagon_M2_mmacls_rs0>; +def Hexagon_M2_mmacls_s0: + di_MInst_dididi_acc_sat <"vmpyweh", int_hexagon_M2_mmacls_s0>; +def Hexagon_M2_mmachs_rs1: + di_MInst_dididi_acc_s1_rnd_sat <"vmpywoh", int_hexagon_M2_mmachs_rs1>; +def Hexagon_M2_mmachs_s1: + di_MInst_dididi_acc_s1_sat <"vmpywoh", int_hexagon_M2_mmachs_s1>; +def Hexagon_M2_mmachs_rs0: + di_MInst_dididi_acc_rnd_sat <"vmpywoh", int_hexagon_M2_mmachs_rs0>; +def Hexagon_M2_mmachs_s0: + di_MInst_dididi_acc_sat <"vmpywoh", int_hexagon_M2_mmachs_s0>; + +// MTYPE / MPYH / Multiply word by unsigned half (32x16). +//Rdd[+]=vmpywouh(Rss,Rtt)[:<<1][:rnd][:sat] +//Rdd[+]=vmpyweuh(Rss,Rtt)[:<<1][:rnd][:sat] +def Hexagon_M2_mmpyul_rs1: + di_MInst_didi_s1_rnd_sat <"vmpyweuh", int_hexagon_M2_mmpyul_rs1>; +def Hexagon_M2_mmpyul_s1: + di_MInst_didi_s1_sat <"vmpyweuh", int_hexagon_M2_mmpyul_s1>; +def Hexagon_M2_mmpyul_rs0: + di_MInst_didi_rnd_sat <"vmpyweuh", int_hexagon_M2_mmpyul_rs0>; +def Hexagon_M2_mmpyul_s0: + di_MInst_didi_sat <"vmpyweuh", int_hexagon_M2_mmpyul_s0>; +def Hexagon_M2_mmpyuh_rs1: + di_MInst_didi_s1_rnd_sat <"vmpywouh", int_hexagon_M2_mmpyuh_rs1>; +def Hexagon_M2_mmpyuh_s1: + di_MInst_didi_s1_sat <"vmpywouh", int_hexagon_M2_mmpyuh_s1>; +def Hexagon_M2_mmpyuh_rs0: + di_MInst_didi_rnd_sat <"vmpywouh", int_hexagon_M2_mmpyuh_rs0>; +def Hexagon_M2_mmpyuh_s0: + di_MInst_didi_sat <"vmpywouh", int_hexagon_M2_mmpyuh_s0>; +def Hexagon_M2_mmaculs_rs1: + di_MInst_dididi_acc_s1_rnd_sat <"vmpyweuh", int_hexagon_M2_mmaculs_rs1>; +def Hexagon_M2_mmaculs_s1: + di_MInst_dididi_acc_s1_sat <"vmpyweuh", int_hexagon_M2_mmaculs_s1>; +def Hexagon_M2_mmaculs_rs0: + di_MInst_dididi_acc_rnd_sat <"vmpyweuh", int_hexagon_M2_mmaculs_rs0>; +def Hexagon_M2_mmaculs_s0: + di_MInst_dididi_acc_sat <"vmpyweuh", int_hexagon_M2_mmaculs_s0>; +def Hexagon_M2_mmacuhs_rs1: + di_MInst_dididi_acc_s1_rnd_sat <"vmpywouh", int_hexagon_M2_mmacuhs_rs1>; +def Hexagon_M2_mmacuhs_s1: + di_MInst_dididi_acc_s1_sat <"vmpywouh", int_hexagon_M2_mmacuhs_s1>; +def Hexagon_M2_mmacuhs_rs0: + di_MInst_dididi_acc_rnd_sat <"vmpywouh", int_hexagon_M2_mmacuhs_rs0>; +def Hexagon_M2_mmacuhs_s0: + di_MInst_dididi_acc_sat <"vmpywouh", int_hexagon_M2_mmacuhs_s0>; + +// MTYPE / MPYH / Multiply and use upper result. +def Hexagon_M2_hmmpyh_rs1: + si_MInst_sisi_h_s1_rnd_sat <"mpy", int_hexagon_M2_hmmpyh_rs1>; +def Hexagon_M2_hmmpyl_rs1: + si_MInst_sisi_l_s1_rnd_sat <"mpy", int_hexagon_M2_hmmpyl_rs1>; +def Hexagon_M2_mpy_up: + si_MInst_sisi <"mpy", int_hexagon_M2_mpy_up>; +def Hexagon_M2_dpmpyss_rnd_s0: + si_MInst_sisi_rnd <"mpy", int_hexagon_M2_dpmpyss_rnd_s0>; +def Hexagon_M2_mpyu_up: + si_MInst_sisi <"mpyu", int_hexagon_M2_mpyu_up>; + +// MTYPE / MPYH / Multiply and use full result. +def Hexagon_M2_dpmpyuu_s0: + di_MInst_sisi <"mpyu", int_hexagon_M2_dpmpyuu_s0>; +def Hexagon_M2_dpmpyuu_acc_s0: + di_MInst_disisi_acc <"mpyu", int_hexagon_M2_dpmpyuu_acc_s0>; +def Hexagon_M2_dpmpyuu_nac_s0: + di_MInst_disisi_nac <"mpyu", int_hexagon_M2_dpmpyuu_nac_s0>; +def Hexagon_M2_dpmpyss_s0: + di_MInst_sisi <"mpy", int_hexagon_M2_dpmpyss_s0>; +def Hexagon_M2_dpmpyss_acc_s0: + di_MInst_disisi_acc <"mpy", int_hexagon_M2_dpmpyss_acc_s0>; +def Hexagon_M2_dpmpyss_nac_s0: + di_MInst_disisi_nac <"mpy", int_hexagon_M2_dpmpyss_nac_s0>; + + +/******************************************************************** +* MTYPE/MPYS * +*********************************************************************/ + +// MTYPE / MPYS / Scalar 16x16 multiply signed. +//Rd=mpy(Rs.[H|L],Rt.[H|L:<<0|:<<1]| +// [:<<0[:rnd|:sat|:rnd:sat]|:<<1[:rnd|:sat|:rnd:sat]]] +def Hexagon_M2_mpy_hh_s0: + si_MInst_sisi_hh <"mpy", int_hexagon_M2_mpy_hh_s0>; +def Hexagon_M2_mpy_hh_s1: + si_MInst_sisi_hh_s1 <"mpy", int_hexagon_M2_mpy_hh_s1>; +def Hexagon_M2_mpy_rnd_hh_s1: + si_MInst_sisi_rnd_hh_s1 <"mpy", int_hexagon_M2_mpy_rnd_hh_s1>; +def Hexagon_M2_mpy_sat_rnd_hh_s1: + si_MInst_sisi_sat_rnd_hh_s1 <"mpy", int_hexagon_M2_mpy_sat_rnd_hh_s1>; +def Hexagon_M2_mpy_sat_hh_s1: + si_MInst_sisi_sat_hh_s1 <"mpy", int_hexagon_M2_mpy_sat_hh_s1>; +def Hexagon_M2_mpy_rnd_hh_s0: + si_MInst_sisi_rnd_hh <"mpy", int_hexagon_M2_mpy_rnd_hh_s0>; +def Hexagon_M2_mpy_sat_rnd_hh_s0: + si_MInst_sisi_sat_rnd_hh <"mpy", int_hexagon_M2_mpy_sat_rnd_hh_s0>; +def Hexagon_M2_mpy_sat_hh_s0: + si_MInst_sisi_sat_hh <"mpy", int_hexagon_M2_mpy_sat_hh_s0>; + +def Hexagon_M2_mpy_hl_s0: + si_MInst_sisi_hl <"mpy", int_hexagon_M2_mpy_hl_s0>; +def Hexagon_M2_mpy_hl_s1: + si_MInst_sisi_hl_s1 <"mpy", int_hexagon_M2_mpy_hl_s1>; +def Hexagon_M2_mpy_rnd_hl_s1: + si_MInst_sisi_rnd_hl_s1 <"mpy", int_hexagon_M2_mpy_rnd_hl_s1>; +def Hexagon_M2_mpy_sat_rnd_hl_s1: + si_MInst_sisi_sat_rnd_hl_s1 <"mpy", int_hexagon_M2_mpy_sat_rnd_hl_s1>; +def Hexagon_M2_mpy_sat_hl_s1: + si_MInst_sisi_sat_hl_s1 <"mpy", int_hexagon_M2_mpy_sat_hl_s1>; +def Hexagon_M2_mpy_rnd_hl_s0: + si_MInst_sisi_rnd_hl <"mpy", int_hexagon_M2_mpy_rnd_hl_s0>; +def Hexagon_M2_mpy_sat_rnd_hl_s0: + si_MInst_sisi_sat_rnd_hl <"mpy", int_hexagon_M2_mpy_sat_rnd_hl_s0>; +def Hexagon_M2_mpy_sat_hl_s0: + si_MInst_sisi_sat_hl <"mpy", int_hexagon_M2_mpy_sat_hl_s0>; + +def Hexagon_M2_mpy_lh_s0: + si_MInst_sisi_lh <"mpy", int_hexagon_M2_mpy_lh_s0>; +def Hexagon_M2_mpy_lh_s1: + si_MInst_sisi_lh_s1 <"mpy", int_hexagon_M2_mpy_lh_s1>; +def Hexagon_M2_mpy_rnd_lh_s1: + si_MInst_sisi_rnd_lh_s1 <"mpy", int_hexagon_M2_mpy_rnd_lh_s1>; +def Hexagon_M2_mpy_sat_rnd_lh_s1: + si_MInst_sisi_sat_rnd_lh_s1 <"mpy", int_hexagon_M2_mpy_sat_rnd_lh_s1>; +def Hexagon_M2_mpy_sat_lh_s1: + si_MInst_sisi_sat_lh_s1 <"mpy", int_hexagon_M2_mpy_sat_lh_s1>; +def Hexagon_M2_mpy_rnd_lh_s0: + si_MInst_sisi_rnd_lh <"mpy", int_hexagon_M2_mpy_rnd_lh_s0>; +def Hexagon_M2_mpy_sat_rnd_lh_s0: + si_MInst_sisi_sat_rnd_lh <"mpy", int_hexagon_M2_mpy_sat_rnd_lh_s0>; +def Hexagon_M2_mpy_sat_lh_s0: + si_MInst_sisi_sat_lh <"mpy", int_hexagon_M2_mpy_sat_lh_s0>; + +def Hexagon_M2_mpy_ll_s0: + si_MInst_sisi_ll <"mpy", int_hexagon_M2_mpy_ll_s0>; +def Hexagon_M2_mpy_ll_s1: + si_MInst_sisi_ll_s1 <"mpy", int_hexagon_M2_mpy_ll_s1>; +def Hexagon_M2_mpy_rnd_ll_s1: + si_MInst_sisi_rnd_ll_s1 <"mpy", int_hexagon_M2_mpy_rnd_ll_s1>; +def Hexagon_M2_mpy_sat_rnd_ll_s1: + si_MInst_sisi_sat_rnd_ll_s1 <"mpy", int_hexagon_M2_mpy_sat_rnd_ll_s1>; +def Hexagon_M2_mpy_sat_ll_s1: + si_MInst_sisi_sat_ll_s1 <"mpy", int_hexagon_M2_mpy_sat_ll_s1>; +def Hexagon_M2_mpy_rnd_ll_s0: + si_MInst_sisi_rnd_ll <"mpy", int_hexagon_M2_mpy_rnd_ll_s0>; +def Hexagon_M2_mpy_sat_rnd_ll_s0: + si_MInst_sisi_sat_rnd_ll <"mpy", int_hexagon_M2_mpy_sat_rnd_ll_s0>; +def Hexagon_M2_mpy_sat_ll_s0: + si_MInst_sisi_sat_ll <"mpy", int_hexagon_M2_mpy_sat_ll_s0>; + +//Rdd=mpy(Rs.[H|L],Rt.[H|L])[[:<<0|:<<1]|[:<<0:rnd|:<<1:rnd]] +def Hexagon_M2_mpyd_hh_s0: + di_MInst_sisi_hh <"mpy", int_hexagon_M2_mpyd_hh_s0>; +def Hexagon_M2_mpyd_hh_s1: + di_MInst_sisi_hh_s1 <"mpy", int_hexagon_M2_mpyd_hh_s1>; +def Hexagon_M2_mpyd_rnd_hh_s1: + di_MInst_sisi_rnd_hh_s1 <"mpy", int_hexagon_M2_mpyd_rnd_hh_s1>; +def Hexagon_M2_mpyd_rnd_hh_s0: + di_MInst_sisi_rnd_hh <"mpy", int_hexagon_M2_mpyd_rnd_hh_s0>; + +def Hexagon_M2_mpyd_hl_s0: + di_MInst_sisi_hl <"mpy", int_hexagon_M2_mpyd_hl_s0>; +def Hexagon_M2_mpyd_hl_s1: + di_MInst_sisi_hl_s1 <"mpy", int_hexagon_M2_mpyd_hl_s1>; +def Hexagon_M2_mpyd_rnd_hl_s1: + di_MInst_sisi_rnd_hl_s1 <"mpy", int_hexagon_M2_mpyd_rnd_hl_s1>; +def Hexagon_M2_mpyd_rnd_hl_s0: + di_MInst_sisi_rnd_hl <"mpy", int_hexagon_M2_mpyd_rnd_hl_s0>; + +def Hexagon_M2_mpyd_lh_s0: + di_MInst_sisi_lh <"mpy", int_hexagon_M2_mpyd_lh_s0>; +def Hexagon_M2_mpyd_lh_s1: + di_MInst_sisi_lh_s1 <"mpy", int_hexagon_M2_mpyd_lh_s1>; +def Hexagon_M2_mpyd_rnd_lh_s1: + di_MInst_sisi_rnd_lh_s1 <"mpy", int_hexagon_M2_mpyd_rnd_lh_s1>; +def Hexagon_M2_mpyd_rnd_lh_s0: + di_MInst_sisi_rnd_lh <"mpy", int_hexagon_M2_mpyd_rnd_lh_s0>; + +def Hexagon_M2_mpyd_ll_s0: + di_MInst_sisi_ll <"mpy", int_hexagon_M2_mpyd_ll_s0>; +def Hexagon_M2_mpyd_ll_s1: + di_MInst_sisi_ll_s1 <"mpy", int_hexagon_M2_mpyd_ll_s1>; +def Hexagon_M2_mpyd_rnd_ll_s1: + di_MInst_sisi_rnd_ll_s1 <"mpy", int_hexagon_M2_mpyd_rnd_ll_s1>; +def Hexagon_M2_mpyd_rnd_ll_s0: + di_MInst_sisi_rnd_ll <"mpy", int_hexagon_M2_mpyd_rnd_ll_s0>; + +//Rx+=mpy(Rs.[H|L],Rt.[H|L])[[[:<<0|:<<1]|[:<<0:sat|:<<1:sat]] +def Hexagon_M2_mpy_acc_hh_s0: + si_MInst_sisisi_acc_hh <"mpy", int_hexagon_M2_mpy_acc_hh_s0>; +def Hexagon_M2_mpy_acc_hh_s1: + si_MInst_sisisi_acc_hh_s1 <"mpy", int_hexagon_M2_mpy_acc_hh_s1>; +def Hexagon_M2_mpy_acc_sat_hh_s1: + si_MInst_sisisi_acc_sat_hh_s1 <"mpy", int_hexagon_M2_mpy_acc_sat_hh_s1>; +def Hexagon_M2_mpy_acc_sat_hh_s0: + si_MInst_sisisi_acc_sat_hh <"mpy", int_hexagon_M2_mpy_acc_sat_hh_s0>; + +def Hexagon_M2_mpy_acc_hl_s0: + si_MInst_sisisi_acc_hl <"mpy", int_hexagon_M2_mpy_acc_hl_s0>; +def Hexagon_M2_mpy_acc_hl_s1: + si_MInst_sisisi_acc_hl_s1 <"mpy", int_hexagon_M2_mpy_acc_hl_s1>; +def Hexagon_M2_mpy_acc_sat_hl_s1: + si_MInst_sisisi_acc_sat_hl_s1 <"mpy", int_hexagon_M2_mpy_acc_sat_hl_s1>; +def Hexagon_M2_mpy_acc_sat_hl_s0: + si_MInst_sisisi_acc_sat_hl <"mpy", int_hexagon_M2_mpy_acc_sat_hl_s0>; + +def Hexagon_M2_mpy_acc_lh_s0: + si_MInst_sisisi_acc_lh <"mpy", int_hexagon_M2_mpy_acc_lh_s0>; +def Hexagon_M2_mpy_acc_lh_s1: + si_MInst_sisisi_acc_lh_s1 <"mpy", int_hexagon_M2_mpy_acc_lh_s1>; +def Hexagon_M2_mpy_acc_sat_lh_s1: + si_MInst_sisisi_acc_sat_lh_s1 <"mpy", int_hexagon_M2_mpy_acc_sat_lh_s1>; +def Hexagon_M2_mpy_acc_sat_lh_s0: + si_MInst_sisisi_acc_sat_lh <"mpy", int_hexagon_M2_mpy_acc_sat_lh_s0>; + +def Hexagon_M2_mpy_acc_ll_s0: + si_MInst_sisisi_acc_ll <"mpy", int_hexagon_M2_mpy_acc_ll_s0>; +def Hexagon_M2_mpy_acc_ll_s1: + si_MInst_sisisi_acc_ll_s1 <"mpy", int_hexagon_M2_mpy_acc_ll_s1>; +def Hexagon_M2_mpy_acc_sat_ll_s1: + si_MInst_sisisi_acc_sat_ll_s1 <"mpy", int_hexagon_M2_mpy_acc_sat_ll_s1>; +def Hexagon_M2_mpy_acc_sat_ll_s0: + si_MInst_sisisi_acc_sat_ll <"mpy", int_hexagon_M2_mpy_acc_sat_ll_s0>; + +//Rx-=mpy(Rs.[H|L],Rt.[H|L])[[[:<<0|:<<1]|[:<<0:sat|:<<1:sat]] +def Hexagon_M2_mpy_nac_hh_s0: + si_MInst_sisisi_nac_hh <"mpy", int_hexagon_M2_mpy_nac_hh_s0>; +def Hexagon_M2_mpy_nac_hh_s1: + si_MInst_sisisi_nac_hh_s1 <"mpy", int_hexagon_M2_mpy_nac_hh_s1>; +def Hexagon_M2_mpy_nac_sat_hh_s1: + si_MInst_sisisi_nac_sat_hh_s1 <"mpy", int_hexagon_M2_mpy_nac_sat_hh_s1>; +def Hexagon_M2_mpy_nac_sat_hh_s0: + si_MInst_sisisi_nac_sat_hh <"mpy", int_hexagon_M2_mpy_nac_sat_hh_s0>; + +def Hexagon_M2_mpy_nac_hl_s0: + si_MInst_sisisi_nac_hl <"mpy", int_hexagon_M2_mpy_nac_hl_s0>; +def Hexagon_M2_mpy_nac_hl_s1: + si_MInst_sisisi_nac_hl_s1 <"mpy", int_hexagon_M2_mpy_nac_hl_s1>; +def Hexagon_M2_mpy_nac_sat_hl_s1: + si_MInst_sisisi_nac_sat_hl_s1 <"mpy", int_hexagon_M2_mpy_nac_sat_hl_s1>; +def Hexagon_M2_mpy_nac_sat_hl_s0: + si_MInst_sisisi_nac_sat_hl <"mpy", int_hexagon_M2_mpy_nac_sat_hl_s0>; + +def Hexagon_M2_mpy_nac_lh_s0: + si_MInst_sisisi_nac_lh <"mpy", int_hexagon_M2_mpy_nac_lh_s0>; +def Hexagon_M2_mpy_nac_lh_s1: + si_MInst_sisisi_nac_lh_s1 <"mpy", int_hexagon_M2_mpy_nac_lh_s1>; +def Hexagon_M2_mpy_nac_sat_lh_s1: + si_MInst_sisisi_nac_sat_lh_s1 <"mpy", int_hexagon_M2_mpy_nac_sat_lh_s1>; +def Hexagon_M2_mpy_nac_sat_lh_s0: + si_MInst_sisisi_nac_sat_lh <"mpy", int_hexagon_M2_mpy_nac_sat_lh_s0>; + +def Hexagon_M2_mpy_nac_ll_s0: + si_MInst_sisisi_nac_ll <"mpy", int_hexagon_M2_mpy_nac_ll_s0>; +def Hexagon_M2_mpy_nac_ll_s1: + si_MInst_sisisi_nac_ll_s1 <"mpy", int_hexagon_M2_mpy_nac_ll_s1>; +def Hexagon_M2_mpy_nac_sat_ll_s1: + si_MInst_sisisi_nac_sat_ll_s1 <"mpy", int_hexagon_M2_mpy_nac_sat_ll_s1>; +def Hexagon_M2_mpy_nac_sat_ll_s0: + si_MInst_sisisi_nac_sat_ll <"mpy", int_hexagon_M2_mpy_nac_sat_ll_s0>; + +//Rx+=mpy(Rs.[H|L],Rt.[H|L:<<0|:<<1] +def Hexagon_M2_mpyd_acc_hh_s0: + di_MInst_disisi_acc_hh <"mpy", int_hexagon_M2_mpyd_acc_hh_s0>; +def Hexagon_M2_mpyd_acc_hh_s1: + di_MInst_disisi_acc_hh_s1 <"mpy", int_hexagon_M2_mpyd_acc_hh_s1>; + +def Hexagon_M2_mpyd_acc_hl_s0: + di_MInst_disisi_acc_hl <"mpy", int_hexagon_M2_mpyd_acc_hl_s0>; +def Hexagon_M2_mpyd_acc_hl_s1: + di_MInst_disisi_acc_hl_s1 <"mpy", int_hexagon_M2_mpyd_acc_hl_s1>; + +def Hexagon_M2_mpyd_acc_lh_s0: + di_MInst_disisi_acc_lh <"mpy", int_hexagon_M2_mpyd_acc_lh_s0>; +def Hexagon_M2_mpyd_acc_lh_s1: + di_MInst_disisi_acc_lh_s1 <"mpy", int_hexagon_M2_mpyd_acc_lh_s1>; + +def Hexagon_M2_mpyd_acc_ll_s0: + di_MInst_disisi_acc_ll <"mpy", int_hexagon_M2_mpyd_acc_ll_s0>; +def Hexagon_M2_mpyd_acc_ll_s1: + di_MInst_disisi_acc_ll_s1 <"mpy", int_hexagon_M2_mpyd_acc_ll_s1>; + +//Rx-=mpy(Rs.[H|L],Rt.[H|L:<<0|:<<1] +def Hexagon_M2_mpyd_nac_hh_s0: + di_MInst_disisi_nac_hh <"mpy", int_hexagon_M2_mpyd_nac_hh_s0>; +def Hexagon_M2_mpyd_nac_hh_s1: + di_MInst_disisi_nac_hh_s1 <"mpy", int_hexagon_M2_mpyd_nac_hh_s1>; + +def Hexagon_M2_mpyd_nac_hl_s0: + di_MInst_disisi_nac_hl <"mpy", int_hexagon_M2_mpyd_nac_hl_s0>; +def Hexagon_M2_mpyd_nac_hl_s1: + di_MInst_disisi_nac_hl_s1 <"mpy", int_hexagon_M2_mpyd_nac_hl_s1>; + +def Hexagon_M2_mpyd_nac_lh_s0: + di_MInst_disisi_nac_lh <"mpy", int_hexagon_M2_mpyd_nac_lh_s0>; +def Hexagon_M2_mpyd_nac_lh_s1: + di_MInst_disisi_nac_lh_s1 <"mpy", int_hexagon_M2_mpyd_nac_lh_s1>; + +def Hexagon_M2_mpyd_nac_ll_s0: + di_MInst_disisi_nac_ll <"mpy", int_hexagon_M2_mpyd_nac_ll_s0>; +def Hexagon_M2_mpyd_nac_ll_s1: + di_MInst_disisi_nac_ll_s1 <"mpy", int_hexagon_M2_mpyd_nac_ll_s1>; + +// MTYPE / MPYS / Scalar 16x16 multiply unsigned. +//Rd=mpyu(Rs.[H|L],Rt.[H|L])[:<<0|:<<1] +def Hexagon_M2_mpyu_hh_s0: + si_MInst_sisi_hh <"mpyu", int_hexagon_M2_mpyu_hh_s0>; +def Hexagon_M2_mpyu_hh_s1: + si_MInst_sisi_hh_s1 <"mpyu", int_hexagon_M2_mpyu_hh_s1>; +def Hexagon_M2_mpyu_hl_s0: + si_MInst_sisi_hl <"mpyu", int_hexagon_M2_mpyu_hl_s0>; +def Hexagon_M2_mpyu_hl_s1: + si_MInst_sisi_hl_s1 <"mpyu", int_hexagon_M2_mpyu_hl_s1>; +def Hexagon_M2_mpyu_lh_s0: + si_MInst_sisi_lh <"mpyu", int_hexagon_M2_mpyu_lh_s0>; +def Hexagon_M2_mpyu_lh_s1: + si_MInst_sisi_lh_s1 <"mpyu", int_hexagon_M2_mpyu_lh_s1>; +def Hexagon_M2_mpyu_ll_s0: + si_MInst_sisi_ll <"mpyu", int_hexagon_M2_mpyu_ll_s0>; +def Hexagon_M2_mpyu_ll_s1: + si_MInst_sisi_ll_s1 <"mpyu", int_hexagon_M2_mpyu_ll_s1>; + +//Rdd=mpyu(Rs.[H|L],Rt.[H|L])[:<<0|:<<1] +def Hexagon_M2_mpyud_hh_s0: + di_MInst_sisi_hh <"mpyu", int_hexagon_M2_mpyud_hh_s0>; +def Hexagon_M2_mpyud_hh_s1: + di_MInst_sisi_hh_s1 <"mpyu", int_hexagon_M2_mpyud_hh_s1>; +def Hexagon_M2_mpyud_hl_s0: + di_MInst_sisi_hl <"mpyu", int_hexagon_M2_mpyud_hl_s0>; +def Hexagon_M2_mpyud_hl_s1: + di_MInst_sisi_hl_s1 <"mpyu", int_hexagon_M2_mpyud_hl_s1>; +def Hexagon_M2_mpyud_lh_s0: + di_MInst_sisi_lh <"mpyu", int_hexagon_M2_mpyud_lh_s0>; +def Hexagon_M2_mpyud_lh_s1: + di_MInst_sisi_lh_s1 <"mpyu", int_hexagon_M2_mpyud_lh_s1>; +def Hexagon_M2_mpyud_ll_s0: + di_MInst_sisi_ll <"mpyu", int_hexagon_M2_mpyud_ll_s0>; +def Hexagon_M2_mpyud_ll_s1: + di_MInst_sisi_ll_s1 <"mpyu", int_hexagon_M2_mpyud_ll_s1>; + +//Rd+=mpyu(Rs.[H|L],Rt.[H|L])[:<<0|:<<1] +def Hexagon_M2_mpyu_acc_hh_s0: + si_MInst_sisisi_acc_hh <"mpyu", int_hexagon_M2_mpyu_acc_hh_s0>; +def Hexagon_M2_mpyu_acc_hh_s1: + si_MInst_sisisi_acc_hh_s1 <"mpyu", int_hexagon_M2_mpyu_acc_hh_s1>; +def Hexagon_M2_mpyu_acc_hl_s0: + si_MInst_sisisi_acc_hl <"mpyu", int_hexagon_M2_mpyu_acc_hl_s0>; +def Hexagon_M2_mpyu_acc_hl_s1: + si_MInst_sisisi_acc_hl_s1 <"mpyu", int_hexagon_M2_mpyu_acc_hl_s1>; +def Hexagon_M2_mpyu_acc_lh_s0: + si_MInst_sisisi_acc_lh <"mpyu", int_hexagon_M2_mpyu_acc_lh_s0>; +def Hexagon_M2_mpyu_acc_lh_s1: + si_MInst_sisisi_acc_lh_s1 <"mpyu", int_hexagon_M2_mpyu_acc_lh_s1>; +def Hexagon_M2_mpyu_acc_ll_s0: + si_MInst_sisisi_acc_ll <"mpyu", int_hexagon_M2_mpyu_acc_ll_s0>; +def Hexagon_M2_mpyu_acc_ll_s1: + si_MInst_sisisi_acc_ll_s1 <"mpyu", int_hexagon_M2_mpyu_acc_ll_s1>; + +//Rd+=mpyu(Rs.[H|L],Rt.[H|L])[:<<0|:<<1] +def Hexagon_M2_mpyu_nac_hh_s0: + si_MInst_sisisi_nac_hh <"mpyu", int_hexagon_M2_mpyu_nac_hh_s0>; +def Hexagon_M2_mpyu_nac_hh_s1: + si_MInst_sisisi_nac_hh_s1 <"mpyu", int_hexagon_M2_mpyu_nac_hh_s1>; +def Hexagon_M2_mpyu_nac_hl_s0: + si_MInst_sisisi_nac_hl <"mpyu", int_hexagon_M2_mpyu_nac_hl_s0>; +def Hexagon_M2_mpyu_nac_hl_s1: + si_MInst_sisisi_nac_hl_s1 <"mpyu", int_hexagon_M2_mpyu_nac_hl_s1>; +def Hexagon_M2_mpyu_nac_lh_s0: + si_MInst_sisisi_nac_lh <"mpyu", int_hexagon_M2_mpyu_nac_lh_s0>; +def Hexagon_M2_mpyu_nac_lh_s1: + si_MInst_sisisi_nac_lh_s1 <"mpyu", int_hexagon_M2_mpyu_nac_lh_s1>; +def Hexagon_M2_mpyu_nac_ll_s0: + si_MInst_sisisi_nac_ll <"mpyu", int_hexagon_M2_mpyu_nac_ll_s0>; +def Hexagon_M2_mpyu_nac_ll_s1: + si_MInst_sisisi_nac_ll_s1 <"mpyu", int_hexagon_M2_mpyu_nac_ll_s1>; + +//Rdd+=mpyu(Rs.[H|L],Rt.[H|L])[:<<0|:<<1] +def Hexagon_M2_mpyud_acc_hh_s0: + di_MInst_disisi_acc_hh <"mpyu", int_hexagon_M2_mpyud_acc_hh_s0>; +def Hexagon_M2_mpyud_acc_hh_s1: + di_MInst_disisi_acc_hh_s1 <"mpyu", int_hexagon_M2_mpyud_acc_hh_s1>; +def Hexagon_M2_mpyud_acc_hl_s0: + di_MInst_disisi_acc_hl <"mpyu", int_hexagon_M2_mpyud_acc_hl_s0>; +def Hexagon_M2_mpyud_acc_hl_s1: + di_MInst_disisi_acc_hl_s1 <"mpyu", int_hexagon_M2_mpyud_acc_hl_s1>; +def Hexagon_M2_mpyud_acc_lh_s0: + di_MInst_disisi_acc_lh <"mpyu", int_hexagon_M2_mpyud_acc_lh_s0>; +def Hexagon_M2_mpyud_acc_lh_s1: + di_MInst_disisi_acc_lh_s1 <"mpyu", int_hexagon_M2_mpyud_acc_lh_s1>; +def Hexagon_M2_mpyud_acc_ll_s0: + di_MInst_disisi_acc_ll <"mpyu", int_hexagon_M2_mpyud_acc_ll_s0>; +def Hexagon_M2_mpyud_acc_ll_s1: + di_MInst_disisi_acc_ll_s1 <"mpyu", int_hexagon_M2_mpyud_acc_ll_s1>; + +//Rdd-=mpyu(Rs.[H|L],Rt.[H|L])[:<<0|:<<1] +def Hexagon_M2_mpyud_nac_hh_s0: + di_MInst_disisi_nac_hh <"mpyu", int_hexagon_M2_mpyud_nac_hh_s0>; +def Hexagon_M2_mpyud_nac_hh_s1: + di_MInst_disisi_nac_hh_s1 <"mpyu", int_hexagon_M2_mpyud_nac_hh_s1>; +def Hexagon_M2_mpyud_nac_hl_s0: + di_MInst_disisi_nac_hl <"mpyu", int_hexagon_M2_mpyud_nac_hl_s0>; +def Hexagon_M2_mpyud_nac_hl_s1: + di_MInst_disisi_nac_hl_s1 <"mpyu", int_hexagon_M2_mpyud_nac_hl_s1>; +def Hexagon_M2_mpyud_nac_lh_s0: + di_MInst_disisi_nac_lh <"mpyu", int_hexagon_M2_mpyud_nac_lh_s0>; +def Hexagon_M2_mpyud_nac_lh_s1: + di_MInst_disisi_nac_lh_s1 <"mpyu", int_hexagon_M2_mpyud_nac_lh_s1>; +def Hexagon_M2_mpyud_nac_ll_s0: + di_MInst_disisi_nac_ll <"mpyu", int_hexagon_M2_mpyud_nac_ll_s0>; +def Hexagon_M2_mpyud_nac_ll_s1: + di_MInst_disisi_nac_ll_s1 <"mpyu", int_hexagon_M2_mpyud_nac_ll_s1>; + + +/******************************************************************** +* MTYPE/VB * +*********************************************************************/ + +// MTYPE / VB / Vector reduce add unsigned bytes. +def Hexagon_A2_vraddub: + di_MInst_didi <"vraddub", int_hexagon_A2_vraddub>; +def Hexagon_A2_vraddub_acc: + di_MInst_dididi_acc <"vraddub", int_hexagon_A2_vraddub_acc>; + +// MTYPE / VB / Vector sum of absolute differences unsigned bytes. +def Hexagon_A2_vrsadub: + di_MInst_didi <"vrsadub", int_hexagon_A2_vrsadub>; +def Hexagon_A2_vrsadub_acc: + di_MInst_dididi_acc <"vrsadub", int_hexagon_A2_vrsadub_acc>; + +/******************************************************************** +* MTYPE/VH * +*********************************************************************/ + +// MTYPE / VH / Vector dual multiply. +def Hexagon_M2_vdmpys_s1: + di_MInst_didi_s1_sat <"vdmpy", int_hexagon_M2_vdmpys_s1>; +def Hexagon_M2_vdmpys_s0: + di_MInst_didi_sat <"vdmpy", int_hexagon_M2_vdmpys_s0>; +def Hexagon_M2_vdmacs_s1: + di_MInst_dididi_acc_s1_sat <"vdmpy", int_hexagon_M2_vdmacs_s1>; +def Hexagon_M2_vdmacs_s0: + di_MInst_dididi_acc_sat <"vdmpy", int_hexagon_M2_vdmacs_s0>; + +// MTYPE / VH / Vector dual multiply with round and pack. +def Hexagon_M2_vdmpyrs_s0: + si_MInst_didi_rnd_sat <"vdmpy", int_hexagon_M2_vdmpyrs_s0>; +def Hexagon_M2_vdmpyrs_s1: + si_MInst_didi_s1_rnd_sat <"vdmpy", int_hexagon_M2_vdmpyrs_s1>; + +// MTYPE / VH / Vector multiply even halfwords. +def Hexagon_M2_vmpy2es_s1: + di_MInst_didi_s1_sat <"vmpyeh", int_hexagon_M2_vmpy2es_s1>; +def Hexagon_M2_vmpy2es_s0: + di_MInst_didi_sat <"vmpyeh", int_hexagon_M2_vmpy2es_s0>; +def Hexagon_M2_vmac2es: + di_MInst_dididi_acc <"vmpyeh", int_hexagon_M2_vmac2es>; +def Hexagon_M2_vmac2es_s1: + di_MInst_dididi_acc_s1_sat <"vmpyeh", int_hexagon_M2_vmac2es_s1>; +def Hexagon_M2_vmac2es_s0: + di_MInst_dididi_acc_sat <"vmpyeh", int_hexagon_M2_vmac2es_s0>; + +// MTYPE / VH / Vector multiply halfwords. +def Hexagon_M2_vmpy2s_s0: + di_MInst_sisi_sat <"vmpyh", int_hexagon_M2_vmpy2s_s0>; +def Hexagon_M2_vmpy2s_s1: + di_MInst_sisi_s1_sat <"vmpyh", int_hexagon_M2_vmpy2s_s1>; +def Hexagon_M2_vmac2: + di_MInst_disisi_acc <"vmpyh", int_hexagon_M2_vmac2>; +def Hexagon_M2_vmac2s_s0: + di_MInst_disisi_acc_sat <"vmpyh", int_hexagon_M2_vmac2s_s0>; +def Hexagon_M2_vmac2s_s1: + di_MInst_disisi_acc_s1_sat <"vmpyh", int_hexagon_M2_vmac2s_s1>; + +// MTYPE / VH / Vector multiply halfwords with round and pack. +def Hexagon_M2_vmpy2s_s0pack: + si_MInst_sisi_rnd_sat <"vmpyh", int_hexagon_M2_vmpy2s_s0pack>; +def Hexagon_M2_vmpy2s_s1pack: + si_MInst_sisi_s1_rnd_sat <"vmpyh", int_hexagon_M2_vmpy2s_s1pack>; + +// MTYPE / VH / Vector reduce multiply halfwords. +// Rxx32+=vrmpyh(Rss32,Rtt32) +def Hexagon_M2_vrmpy_s0: + di_MInst_didi <"vrmpyh", int_hexagon_M2_vrmpy_s0>; +def Hexagon_M2_vrmac_s0: + di_MInst_dididi_acc <"vrmpyh", int_hexagon_M2_vrmac_s0>; + + +/******************************************************************** +* STYPE/ALU * +*********************************************************************/ + +// STYPE / ALU / Absolute value. +def Hexagon_A2_abs: + si_SInst_si <"abs", int_hexagon_A2_abs>; +def Hexagon_A2_absp: + di_SInst_di <"abs", int_hexagon_A2_absp>; +def Hexagon_A2_abssat: + si_SInst_si_sat <"abs", int_hexagon_A2_abssat>; + +// STYPE / ALU / Negate. +def Hexagon_A2_negp: + di_SInst_di <"neg", int_hexagon_A2_negp>; +def Hexagon_A2_negsat: + si_SInst_si_sat <"neg", int_hexagon_A2_negsat>; + +// STYPE / ALU / Logical Not. +def Hexagon_A2_notp: + di_SInst_di <"not", int_hexagon_A2_notp>; + +// STYPE / ALU / Sign extend word to doubleword. +def Hexagon_A2_sxtw: + di_SInst_si <"sxtw", int_hexagon_A2_sxtw>; + + +/******************************************************************** +* STYPE/BIT * +*********************************************************************/ + +// STYPE / BIT / Count leading. +def Hexagon_S2_cl0: + si_SInst_si <"cl0", int_hexagon_S2_cl0>; +def Hexagon_S2_cl0p: + si_SInst_di <"cl0", int_hexagon_S2_cl0p>; +def Hexagon_S2_cl1: + si_SInst_si <"cl1", int_hexagon_S2_cl1>; +def Hexagon_S2_cl1p: + si_SInst_di <"cl1", int_hexagon_S2_cl1p>; +def Hexagon_S2_clb: + si_SInst_si <"clb", int_hexagon_S2_clb>; +def Hexagon_S2_clbp: + si_SInst_di <"clb", int_hexagon_S2_clbp>; +def Hexagon_S2_clbnorm: + si_SInst_si <"normamt", int_hexagon_S2_clbnorm>; + +// STYPE / BIT / Count trailing. +def Hexagon_S2_ct0: + si_SInst_si <"ct0", int_hexagon_S2_ct0>; +def Hexagon_S2_ct1: + si_SInst_si <"ct1", int_hexagon_S2_ct1>; + +// STYPE / BIT / Compare bit mask. +def HEXAGON_C2_bitsclr: + qi_SInst_sisi <"bitsclr", int_hexagon_C2_bitsclr>; +def HEXAGON_C2_bitsclri: + qi_SInst_siu6 <"bitsclr", int_hexagon_C2_bitsclri>; +def HEXAGON_C2_bitsset: + qi_SInst_sisi <"bitsset", int_hexagon_C2_bitsset>; + +// STYPE / BIT / Extract unsigned. +// Rd[d][32/64]=extractu(Rs[s],Rt[t],[imm]) +def Hexagon_S2_extractu: + si_SInst_siu5u5 <"extractu",int_hexagon_S2_extractu>; +def Hexagon_S2_extractu_rp: + si_SInst_sidi <"extractu",int_hexagon_S2_extractu_rp>; +def Hexagon_S2_extractup: + di_SInst_diu6u6 <"extractu",int_hexagon_S2_extractup>; +def Hexagon_S2_extractup_rp: + di_SInst_didi <"extractu",int_hexagon_S2_extractup_rp>; + +// STYPE / BIT / Insert bitfield. +def HEXAGON_S2_insert: + si_SInst_sisiu5u5 <"insert", int_hexagon_S2_insert>; +def HEXAGON_S2_insert_rp: + si_SInst_sisidi <"insert", int_hexagon_S2_insert_rp>; +def HEXAGON_S2_insertp: + di_SInst_didiu6u6 <"insert", int_hexagon_S2_insertp>; +def HEXAGON_S2_insertp_rp: + di_SInst_dididi <"insert", int_hexagon_S2_insertp_rp>; + +// STYPE / BIT / Innterleave/deinterleave. +def HEXAGON_S2_interleave: + di_SInst_di <"interleave", int_hexagon_S2_interleave>; +def HEXAGON_S2_deinterleave: + di_SInst_di <"deinterleave", int_hexagon_S2_deinterleave>; + +// STYPE / BIT / Linear feedback-shift Iteration. +def HEXAGON_S2_lfsp: + di_SInst_didi <"lfs", int_hexagon_S2_lfsp>; + +// STYPE / BIT / Bit reverse. +def HEXAGON_S2_brev: + si_SInst_si <"brev", int_hexagon_S2_brev>; + +// STYPE / BIT / Set/Clear/Toggle Bit. +def Hexagon_S2_setbit_i: + si_SInst_siu5 <"setbit", int_hexagon_S2_setbit_i>; +def Hexagon_S2_togglebit_i: + si_SInst_siu5 <"togglebit", int_hexagon_S2_togglebit_i>; +def Hexagon_S2_clrbit_i: + si_SInst_siu5 <"clrbit", int_hexagon_S2_clrbit_i>; +def Hexagon_S2_setbit_r: + si_SInst_sisi <"setbit", int_hexagon_S2_setbit_r>; +def Hexagon_S2_togglebit_r: + si_SInst_sisi <"togglebit", int_hexagon_S2_togglebit_r>; +def Hexagon_S2_clrbit_r: + si_SInst_sisi <"clrbit", int_hexagon_S2_clrbit_r>; + +// STYPE / BIT / Test Bit. +def Hexagon_S2_tstbit_i: + qi_SInst_siu5 <"tstbit", int_hexagon_S2_tstbit_i>; +def Hexagon_S2_tstbit_r: + qi_SInst_sisi <"tstbit", int_hexagon_S2_tstbit_r>; + + +/******************************************************************** +* STYPE/COMPLEX * +*********************************************************************/ + +// STYPE / COMPLEX / Vector Complex conjugate. +def Hexagon_A2_vconj: + di_SInst_di_sat <"vconj", int_hexagon_A2_vconj>; + +// STYPE / COMPLEX / Vector Complex rotate. +def Hexagon_S2_vcrotate: + di_SInst_disi <"vcrotate",int_hexagon_S2_vcrotate>; + + +/******************************************************************** +* STYPE/PERM * +*********************************************************************/ + +// STYPE / PERM / Saturate. +def Hexagon_A2_sat: + si_SInst_di <"sat", int_hexagon_A2_sat>; +def Hexagon_A2_satb: + si_SInst_si <"satb", int_hexagon_A2_satb>; +def Hexagon_A2_sath: + si_SInst_si <"sath", int_hexagon_A2_sath>; +def Hexagon_A2_satub: + si_SInst_si <"satub", int_hexagon_A2_satub>; +def Hexagon_A2_satuh: + si_SInst_si <"satuh", int_hexagon_A2_satuh>; + +// STYPE / PERM / Swizzle bytes. +def Hexagon_A2_swiz: + si_SInst_si <"swiz", int_hexagon_A2_swiz>; + +// STYPE / PERM / Vector align. +// Need custom lowering +def Hexagon_S2_valignib: + di_SInst_didiu3 <"valignb", int_hexagon_S2_valignib>; +def Hexagon_S2_valignrb: + di_SInst_didiqi <"valignb", int_hexagon_S2_valignrb>; + +// STYPE / PERM / Vector round and pack. +def Hexagon_S2_vrndpackwh: + si_SInst_di <"vrndwh", int_hexagon_S2_vrndpackwh>; +def Hexagon_S2_vrndpackwhs: + si_SInst_di_sat <"vrndwh", int_hexagon_S2_vrndpackwhs>; + +// STYPE / PERM / Vector saturate and pack. +def Hexagon_S2_svsathb: + si_SInst_si <"vsathb", int_hexagon_S2_svsathb>; +def Hexagon_S2_vsathb: + si_SInst_di <"vsathb", int_hexagon_S2_vsathb>; +def Hexagon_S2_svsathub: + si_SInst_si <"vsathub", int_hexagon_S2_svsathub>; +def Hexagon_S2_vsathub: + si_SInst_di <"vsathub", int_hexagon_S2_vsathub>; +def Hexagon_S2_vsatwh: + si_SInst_di <"vsatwh", int_hexagon_S2_vsatwh>; +def Hexagon_S2_vsatwuh: + si_SInst_di <"vsatwuh", int_hexagon_S2_vsatwuh>; + +// STYPE / PERM / Vector saturate without pack. +def Hexagon_S2_vsathb_nopack: + di_SInst_di <"vsathb", int_hexagon_S2_vsathb_nopack>; +def Hexagon_S2_vsathub_nopack: + di_SInst_di <"vsathub", int_hexagon_S2_vsathub_nopack>; +def Hexagon_S2_vsatwh_nopack: + di_SInst_di <"vsatwh", int_hexagon_S2_vsatwh_nopack>; +def Hexagon_S2_vsatwuh_nopack: + di_SInst_di <"vsatwuh", int_hexagon_S2_vsatwuh_nopack>; + +// STYPE / PERM / Vector shuffle. +def Hexagon_S2_shuffeb: + di_SInst_didi <"shuffeb", int_hexagon_S2_shuffeb>; +def Hexagon_S2_shuffeh: + di_SInst_didi <"shuffeh", int_hexagon_S2_shuffeh>; +def Hexagon_S2_shuffob: + di_SInst_didi <"shuffob", int_hexagon_S2_shuffob>; +def Hexagon_S2_shuffoh: + di_SInst_didi <"shuffoh", int_hexagon_S2_shuffoh>; + +// STYPE / PERM / Vector splat bytes. +def Hexagon_S2_vsplatrb: + si_SInst_si <"vsplatb", int_hexagon_S2_vsplatrb>; + +// STYPE / PERM / Vector splat halfwords. +def Hexagon_S2_vsplatrh: + di_SInst_si <"vsplath", int_hexagon_S2_vsplatrh>; + +// STYPE / PERM / Vector splice. +def HEXAGON_S2_vsplicerb: + di_SInst_didiqi <"vspliceb",int_hexagon_S2_vsplicerb>; +def HEXAGON_S2_vspliceib: + di_SInst_didiu3 <"vspliceb",int_hexagon_S2_vspliceib>; + +// STYPE / PERM / Sign extend. +def Hexagon_S2_vsxtbh: + di_SInst_si <"vsxtbh", int_hexagon_S2_vsxtbh>; +def Hexagon_S2_vsxthw: + di_SInst_si <"vsxthw", int_hexagon_S2_vsxthw>; + +// STYPE / PERM / Truncate. +def Hexagon_S2_vtrunehb: + si_SInst_di <"vtrunehb",int_hexagon_S2_vtrunehb>; +def Hexagon_S2_vtrunohb: + si_SInst_di <"vtrunohb",int_hexagon_S2_vtrunohb>; +def Hexagon_S2_vtrunewh: + di_SInst_didi <"vtrunewh",int_hexagon_S2_vtrunewh>; +def Hexagon_S2_vtrunowh: + di_SInst_didi <"vtrunowh",int_hexagon_S2_vtrunowh>; + +// STYPE / PERM / Zero extend. +def Hexagon_S2_vzxtbh: + di_SInst_si <"vzxtbh", int_hexagon_S2_vzxtbh>; +def Hexagon_S2_vzxthw: + di_SInst_si <"vzxthw", int_hexagon_S2_vzxthw>; + + +/******************************************************************** +* STYPE/PRED * +*********************************************************************/ + +// STYPE / PRED / Mask generate from predicate. +def Hexagon_C2_mask: + di_SInst_qi <"mask", int_hexagon_C2_mask>; + +// STYPE / PRED / Predicate transfer. +def Hexagon_C2_tfrpr: + si_SInst_qi <"", int_hexagon_C2_tfrpr>; +def Hexagon_C2_tfrrp: + qi_SInst_si <"", int_hexagon_C2_tfrrp>; + +// STYPE / PRED / Viterbi pack even and odd predicate bits. +def Hexagon_C2_vitpack: + si_SInst_qiqi <"vitpack",int_hexagon_C2_vitpack>; + + +/******************************************************************** +* STYPE/SHIFT * +*********************************************************************/ + +// STYPE / SHIFT / Shift by immediate. +def Hexagon_S2_asl_i_r: + si_SInst_siu5 <"asl", int_hexagon_S2_asl_i_r>; +def Hexagon_S2_asr_i_r: + si_SInst_siu5 <"asr", int_hexagon_S2_asr_i_r>; +def Hexagon_S2_lsr_i_r: + si_SInst_siu5 <"lsr", int_hexagon_S2_lsr_i_r>; +def Hexagon_S2_asl_i_p: + di_SInst_diu6 <"asl", int_hexagon_S2_asl_i_p>; +def Hexagon_S2_asr_i_p: + di_SInst_diu6 <"asr", int_hexagon_S2_asr_i_p>; +def Hexagon_S2_lsr_i_p: + di_SInst_diu6 <"lsr", int_hexagon_S2_lsr_i_p>; + +// STYPE / SHIFT / Shift by immediate and accumulate. +def Hexagon_S2_asl_i_r_acc: + si_SInst_sisiu5_acc <"asl", int_hexagon_S2_asl_i_r_acc>; +def Hexagon_S2_asr_i_r_acc: + si_SInst_sisiu5_acc <"asr", int_hexagon_S2_asr_i_r_acc>; +def Hexagon_S2_lsr_i_r_acc: + si_SInst_sisiu5_acc <"lsr", int_hexagon_S2_lsr_i_r_acc>; +def Hexagon_S2_asl_i_r_nac: + si_SInst_sisiu5_nac <"asl", int_hexagon_S2_asl_i_r_nac>; +def Hexagon_S2_asr_i_r_nac: + si_SInst_sisiu5_nac <"asr", int_hexagon_S2_asr_i_r_nac>; +def Hexagon_S2_lsr_i_r_nac: + si_SInst_sisiu5_nac <"lsr", int_hexagon_S2_lsr_i_r_nac>; +def Hexagon_S2_asl_i_p_acc: + di_SInst_didiu6_acc <"asl", int_hexagon_S2_asl_i_p_acc>; +def Hexagon_S2_asr_i_p_acc: + di_SInst_didiu6_acc <"asr", int_hexagon_S2_asr_i_p_acc>; +def Hexagon_S2_lsr_i_p_acc: + di_SInst_didiu6_acc <"lsr", int_hexagon_S2_lsr_i_p_acc>; +def Hexagon_S2_asl_i_p_nac: + di_SInst_didiu6_nac <"asl", int_hexagon_S2_asl_i_p_nac>; +def Hexagon_S2_asr_i_p_nac: + di_SInst_didiu6_nac <"asr", int_hexagon_S2_asr_i_p_nac>; +def Hexagon_S2_lsr_i_p_nac: + di_SInst_didiu6_nac <"lsr", int_hexagon_S2_lsr_i_p_nac>; + +// STYPE / SHIFT / Shift by immediate and add. +def Hexagon_S2_addasl_rrri: + si_SInst_sisiu3 <"addasl", int_hexagon_S2_addasl_rrri>; + +// STYPE / SHIFT / Shift by immediate and logical. +def Hexagon_S2_asl_i_r_and: + si_SInst_sisiu5_and <"asl", int_hexagon_S2_asl_i_r_and>; +def Hexagon_S2_asr_i_r_and: + si_SInst_sisiu5_and <"asr", int_hexagon_S2_asr_i_r_and>; +def Hexagon_S2_lsr_i_r_and: + si_SInst_sisiu5_and <"lsr", int_hexagon_S2_lsr_i_r_and>; + +def Hexagon_S2_asl_i_r_xacc: + si_SInst_sisiu5_xor <"asl", int_hexagon_S2_asl_i_r_xacc>; +def Hexagon_S2_lsr_i_r_xacc: + si_SInst_sisiu5_xor <"lsr", int_hexagon_S2_lsr_i_r_xacc>; + +def Hexagon_S2_asl_i_r_or: + si_SInst_sisiu5_or <"asl", int_hexagon_S2_asl_i_r_or>; +def Hexagon_S2_asr_i_r_or: + si_SInst_sisiu5_or <"asr", int_hexagon_S2_asr_i_r_or>; +def Hexagon_S2_lsr_i_r_or: + si_SInst_sisiu5_or <"lsr", int_hexagon_S2_lsr_i_r_or>; + +def Hexagon_S2_asl_i_p_and: + di_SInst_didiu6_and <"asl", int_hexagon_S2_asl_i_p_and>; +def Hexagon_S2_asr_i_p_and: + di_SInst_didiu6_and <"asr", int_hexagon_S2_asr_i_p_and>; +def Hexagon_S2_lsr_i_p_and: + di_SInst_didiu6_and <"lsr", int_hexagon_S2_lsr_i_p_and>; + +def Hexagon_S2_asl_i_p_xacc: + di_SInst_didiu6_xor <"asl", int_hexagon_S2_asl_i_p_xacc>; +def Hexagon_S2_lsr_i_p_xacc: + di_SInst_didiu6_xor <"lsr", int_hexagon_S2_lsr_i_p_xacc>; + +def Hexagon_S2_asl_i_p_or: + di_SInst_didiu6_or <"asl", int_hexagon_S2_asl_i_p_or>; +def Hexagon_S2_asr_i_p_or: + di_SInst_didiu6_or <"asr", int_hexagon_S2_asr_i_p_or>; +def Hexagon_S2_lsr_i_p_or: + di_SInst_didiu6_or <"lsr", int_hexagon_S2_lsr_i_p_or>; + +// STYPE / SHIFT / Shift right by immediate with rounding. +def Hexagon_S2_asr_i_r_rnd: + si_SInst_siu5_rnd <"asr", int_hexagon_S2_asr_i_r_rnd>; +def Hexagon_S2_asr_i_r_rnd_goodsyntax: + si_SInst_siu5 <"asrrnd", int_hexagon_S2_asr_i_r_rnd_goodsyntax>; + +// STYPE / SHIFT / Shift left by immediate with saturation. +def Hexagon_S2_asl_i_r_sat: + si_SInst_sisi_sat <"asl", int_hexagon_S2_asl_i_r_sat>; + +// STYPE / SHIFT / Shift by register. +def Hexagon_S2_asl_r_r: + si_SInst_sisi <"asl", int_hexagon_S2_asl_r_r>; +def Hexagon_S2_asr_r_r: + si_SInst_sisi <"asr", int_hexagon_S2_asr_r_r>; +def Hexagon_S2_lsl_r_r: + si_SInst_sisi <"lsl", int_hexagon_S2_lsl_r_r>; +def Hexagon_S2_lsr_r_r: + si_SInst_sisi <"lsr", int_hexagon_S2_lsr_r_r>; +def Hexagon_S2_asl_r_p: + di_SInst_disi <"asl", int_hexagon_S2_asl_r_p>; +def Hexagon_S2_asr_r_p: + di_SInst_disi <"asr", int_hexagon_S2_asr_r_p>; +def Hexagon_S2_lsl_r_p: + di_SInst_disi <"lsl", int_hexagon_S2_lsl_r_p>; +def Hexagon_S2_lsr_r_p: + di_SInst_disi <"lsr", int_hexagon_S2_lsr_r_p>; + +// STYPE / SHIFT / Shift by register and accumulate. +def Hexagon_S2_asl_r_r_acc: + si_SInst_sisisi_acc <"asl", int_hexagon_S2_asl_r_r_acc>; +def Hexagon_S2_asr_r_r_acc: + si_SInst_sisisi_acc <"asr", int_hexagon_S2_asr_r_r_acc>; +def Hexagon_S2_lsl_r_r_acc: + si_SInst_sisisi_acc <"lsl", int_hexagon_S2_lsl_r_r_acc>; +def Hexagon_S2_lsr_r_r_acc: + si_SInst_sisisi_acc <"lsr", int_hexagon_S2_lsr_r_r_acc>; +def Hexagon_S2_asl_r_p_acc: + di_SInst_didisi_acc <"asl", int_hexagon_S2_asl_r_p_acc>; +def Hexagon_S2_asr_r_p_acc: + di_SInst_didisi_acc <"asr", int_hexagon_S2_asr_r_p_acc>; +def Hexagon_S2_lsl_r_p_acc: + di_SInst_didisi_acc <"lsl", int_hexagon_S2_lsl_r_p_acc>; +def Hexagon_S2_lsr_r_p_acc: + di_SInst_didisi_acc <"lsr", int_hexagon_S2_lsr_r_p_acc>; + +def Hexagon_S2_asl_r_r_nac: + si_SInst_sisisi_nac <"asl", int_hexagon_S2_asl_r_r_nac>; +def Hexagon_S2_asr_r_r_nac: + si_SInst_sisisi_nac <"asr", int_hexagon_S2_asr_r_r_nac>; +def Hexagon_S2_lsl_r_r_nac: + si_SInst_sisisi_nac <"lsl", int_hexagon_S2_lsl_r_r_nac>; +def Hexagon_S2_lsr_r_r_nac: + si_SInst_sisisi_nac <"lsr", int_hexagon_S2_lsr_r_r_nac>; +def Hexagon_S2_asl_r_p_nac: + di_SInst_didisi_nac <"asl", int_hexagon_S2_asl_r_p_nac>; +def Hexagon_S2_asr_r_p_nac: + di_SInst_didisi_nac <"asr", int_hexagon_S2_asr_r_p_nac>; +def Hexagon_S2_lsl_r_p_nac: + di_SInst_didisi_nac <"lsl", int_hexagon_S2_lsl_r_p_nac>; +def Hexagon_S2_lsr_r_p_nac: + di_SInst_didisi_nac <"lsr", int_hexagon_S2_lsr_r_p_nac>; + +// STYPE / SHIFT / Shift by register and logical. +def Hexagon_S2_asl_r_r_and: + si_SInst_sisisi_and <"asl", int_hexagon_S2_asl_r_r_and>; +def Hexagon_S2_asr_r_r_and: + si_SInst_sisisi_and <"asr", int_hexagon_S2_asr_r_r_and>; +def Hexagon_S2_lsl_r_r_and: + si_SInst_sisisi_and <"lsl", int_hexagon_S2_lsl_r_r_and>; +def Hexagon_S2_lsr_r_r_and: + si_SInst_sisisi_and <"lsr", int_hexagon_S2_lsr_r_r_and>; + +def Hexagon_S2_asl_r_r_or: + si_SInst_sisisi_or <"asl", int_hexagon_S2_asl_r_r_or>; +def Hexagon_S2_asr_r_r_or: + si_SInst_sisisi_or <"asr", int_hexagon_S2_asr_r_r_or>; +def Hexagon_S2_lsl_r_r_or: + si_SInst_sisisi_or <"lsl", int_hexagon_S2_lsl_r_r_or>; +def Hexagon_S2_lsr_r_r_or: + si_SInst_sisisi_or <"lsr", int_hexagon_S2_lsr_r_r_or>; + +def Hexagon_S2_asl_r_p_and: + di_SInst_didisi_and <"asl", int_hexagon_S2_asl_r_p_and>; +def Hexagon_S2_asr_r_p_and: + di_SInst_didisi_and <"asr", int_hexagon_S2_asr_r_p_and>; +def Hexagon_S2_lsl_r_p_and: + di_SInst_didisi_and <"lsl", int_hexagon_S2_lsl_r_p_and>; +def Hexagon_S2_lsr_r_p_and: + di_SInst_didisi_and <"lsr", int_hexagon_S2_lsr_r_p_and>; + +def Hexagon_S2_asl_r_p_or: + di_SInst_didisi_or <"asl", int_hexagon_S2_asl_r_p_or>; +def Hexagon_S2_asr_r_p_or: + di_SInst_didisi_or <"asr", int_hexagon_S2_asr_r_p_or>; +def Hexagon_S2_lsl_r_p_or: + di_SInst_didisi_or <"lsl", int_hexagon_S2_lsl_r_p_or>; +def Hexagon_S2_lsr_r_p_or: + di_SInst_didisi_or <"lsr", int_hexagon_S2_lsr_r_p_or>; + +// STYPE / SHIFT / Shift by register with saturation. +def Hexagon_S2_asl_r_r_sat: + si_SInst_sisi_sat <"asl", int_hexagon_S2_asl_r_r_sat>; +def Hexagon_S2_asr_r_r_sat: + si_SInst_sisi_sat <"asr", int_hexagon_S2_asr_r_r_sat>; + +// STYPE / SHIFT / Table Index. +def HEXAGON_S2_tableidxb_goodsyntax: + si_MInst_sisiu4u5 <"tableidxb",int_hexagon_S2_tableidxb_goodsyntax>; +def HEXAGON_S2_tableidxd_goodsyntax: + si_MInst_sisiu4u5 <"tableidxd",int_hexagon_S2_tableidxd_goodsyntax>; +def HEXAGON_S2_tableidxh_goodsyntax: + si_MInst_sisiu4u5 <"tableidxh",int_hexagon_S2_tableidxh_goodsyntax>; +def HEXAGON_S2_tableidxw_goodsyntax: + si_MInst_sisiu4u5 <"tableidxw",int_hexagon_S2_tableidxw_goodsyntax>; + + +/******************************************************************** +* STYPE/VH * +*********************************************************************/ + +// STYPE / VH / Vector absolute value halfwords. +// Rdd64=vabsh(Rss64) +def Hexagon_A2_vabsh: + di_SInst_di <"vabsh", int_hexagon_A2_vabsh>; +def Hexagon_A2_vabshsat: + di_SInst_di_sat <"vabsh", int_hexagon_A2_vabshsat>; + +// STYPE / VH / Vector shift halfwords by immediate. +// Rdd64=v[asl/asr/lsr]h(Rss64,Rt32) +def Hexagon_S2_asl_i_vh: + di_SInst_disi <"vaslh", int_hexagon_S2_asl_i_vh>; +def Hexagon_S2_asr_i_vh: + di_SInst_disi <"vasrh", int_hexagon_S2_asr_i_vh>; +def Hexagon_S2_lsr_i_vh: + di_SInst_disi <"vlsrh", int_hexagon_S2_lsr_i_vh>; + +// STYPE / VH / Vector shift halfwords by register. +// Rdd64=v[asl/asr/lsl/lsr]w(Rss64,Rt32) +def Hexagon_S2_asl_r_vh: + di_SInst_disi <"vaslh", int_hexagon_S2_asl_r_vh>; +def Hexagon_S2_asr_r_vh: + di_SInst_disi <"vasrh", int_hexagon_S2_asr_r_vh>; +def Hexagon_S2_lsl_r_vh: + di_SInst_disi <"vlslh", int_hexagon_S2_lsl_r_vh>; +def Hexagon_S2_lsr_r_vh: + di_SInst_disi <"vlsrh", int_hexagon_S2_lsr_r_vh>; + + +/******************************************************************** +* STYPE/VW * +*********************************************************************/ + +// STYPE / VW / Vector absolute value words. +def Hexagon_A2_vabsw: + di_SInst_di <"vabsw", int_hexagon_A2_vabsw>; +def Hexagon_A2_vabswsat: + di_SInst_di_sat <"vabsw", int_hexagon_A2_vabswsat>; + +// STYPE / VW / Vector shift words by immediate. +// Rdd64=v[asl/vsl]w(Rss64,Rt32) +def Hexagon_S2_asl_i_vw: + di_SInst_disi <"vaslw", int_hexagon_S2_asl_i_vw>; +def Hexagon_S2_asr_i_vw: + di_SInst_disi <"vasrw", int_hexagon_S2_asr_i_vw>; +def Hexagon_S2_lsr_i_vw: + di_SInst_disi <"vlsrw", int_hexagon_S2_lsr_i_vw>; + +// STYPE / VW / Vector shift words by register. +// Rdd64=v[asl/vsl]w(Rss64,Rt32) +def Hexagon_S2_asl_r_vw: + di_SInst_disi <"vaslw", int_hexagon_S2_asl_r_vw>; +def Hexagon_S2_asr_r_vw: + di_SInst_disi <"vasrw", int_hexagon_S2_asr_r_vw>; +def Hexagon_S2_lsl_r_vw: + di_SInst_disi <"vlslw", int_hexagon_S2_lsl_r_vw>; +def Hexagon_S2_lsr_r_vw: + di_SInst_disi <"vlsrw", int_hexagon_S2_lsr_r_vw>; + +// STYPE / VW / Vector shift words with truncate and pack. +def Hexagon_S2_asr_r_svw_trun: + si_SInst_disi <"vasrw", int_hexagon_S2_asr_r_svw_trun>; +def Hexagon_S2_asr_i_svw_trun: + si_SInst_diu5 <"vasrw", int_hexagon_S2_asr_i_svw_trun>; + +include "HexagonIntrinsicsV3.td" +include "HexagonIntrinsicsV4.td" diff --git a/lib/Target/Hexagon/HexagonIntrinsicsDerived.td b/lib/Target/Hexagon/HexagonIntrinsicsDerived.td new file mode 100644 index 0000000000..68eaf68480 --- /dev/null +++ b/lib/Target/Hexagon/HexagonIntrinsicsDerived.td @@ -0,0 +1,29 @@ +//===-- HexagonIntrinsicsDerived.td - Derived intrinsics ---*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Multiply 64-bit and use lower result +// +// Optimized with intrinisics accumulates +// +def : Pat <(mul DoubleRegs:$src1, DoubleRegs:$src2), + (COMBINE_rr + (Hexagon_M2_maci + (Hexagon_M2_maci (EXTRACT_SUBREG (MPYU64 (EXTRACT_SUBREG DoubleRegs:$src1, subreg_loreg), + (EXTRACT_SUBREG DoubleRegs:$src2, subreg_loreg)), + subreg_hireg), + (EXTRACT_SUBREG DoubleRegs:$src1, subreg_loreg), + (EXTRACT_SUBREG DoubleRegs:$src2, subreg_hireg)), + (EXTRACT_SUBREG DoubleRegs:$src2, subreg_loreg), + (EXTRACT_SUBREG DoubleRegs:$src1, subreg_hireg)), + (EXTRACT_SUBREG (MPYU64 (EXTRACT_SUBREG DoubleRegs:$src1, subreg_loreg), + (EXTRACT_SUBREG DoubleRegs:$src2, subreg_loreg)), + subreg_loreg))>; + + + diff --git a/lib/Target/Hexagon/HexagonIntrinsicsV3.td b/lib/Target/Hexagon/HexagonIntrinsicsV3.td new file mode 100644 index 0000000000..2a54e62d20 --- /dev/null +++ b/lib/Target/Hexagon/HexagonIntrinsicsV3.td @@ -0,0 +1,50 @@ +//=- HexagonIntrinsicsV3.td - Target Description for Hexagon -*- tablegen -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the Hexagon V3 Compiler Intrinsics in TableGen format. +// +//===----------------------------------------------------------------------===// + + + + +// MTYPE / COMPLEX / Vector reduce complex multiply real or imaginary. +def Hexagon_M2_vrcmpys_s1: + di_MInst_disi_s1_sat <"vrcmpys", int_hexagon_M2_vrcmpys_s1>; +def Hexagon_M2_vrcmpys_acc_s1: + di_MInst_didisi_acc_s1_sat <"vrcmpys", int_hexagon_M2_vrcmpys_acc_s1>; +def Hexagon_M2_vrcmpys_s1rp: + si_MInst_disi_s1_rnd_sat <"vrcmpys", int_hexagon_M2_vrcmpys_s1rp>; + + + + +/******************************************************************** +* MTYPE/VB * +*********************************************************************/ + +// MTYPE / VB / Vector reduce add unsigned bytes. +def Hexagon_M2_vradduh: + si_MInst_didi <"vradduh", int_hexagon_M2_vradduh>; + + +/******************************************************************** +* ALU64/ALU * +*********************************************************************/ + +// ALU64 / ALU / Add. +def Hexagon_A2_addsp: + di_ALU64_sidi <"add", int_hexagon_A2_addsp>; +def Hexagon_A2_addpsat: + di_ALU64_didi <"add", int_hexagon_A2_addpsat>; + +def Hexagon_A2_maxp: + di_ALU64_didi <"max", int_hexagon_A2_maxp>; +def Hexagon_A2_maxup: + di_ALU64_didi <"maxu", int_hexagon_A2_maxup>; diff --git a/lib/Target/Hexagon/HexagonIntrinsicsV4.td b/lib/Target/Hexagon/HexagonIntrinsicsV4.td new file mode 100644 index 0000000000..dd28ebb572 --- /dev/null +++ b/lib/Target/Hexagon/HexagonIntrinsicsV4.td @@ -0,0 +1,369 @@ +//===- HexagonIntrinsicsV4.td - V4 Instruction intrinsics --*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// This is populated based on the following specs: +// Hexagon V4 Architecture Extensions +// Application-Level Specification +// 80-V9418-12 Rev. A +// June 15, 2010 + + +// +// ALU 32 types. +// + +class si_ALU32_sisi_not<string opc, Intrinsic IntID> + : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, ~$src2)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class di_ALU32_s8si<string opc, Intrinsic IntID> + : ALU32_rr<(outs DoubleRegs:$dst), (ins s8Imm:$src1, IntRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "(#$src1, $src2)")), + [(set DoubleRegs:$dst, (IntID imm:$src1, IntRegs:$src2))]>; + +class di_ALU32_sis8<string opc, Intrinsic IntID> + : ALU32_rr<(outs DoubleRegs:$dst), (ins IntRegs:$src1, s8Imm:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, #$src2)")), + [(set DoubleRegs:$dst, (IntID IntRegs:$src1, imm:$src2))]>; + +class qi_neg_ALU32_sisi<string opc, Intrinsic IntID> + : ALU32_rr<(outs PredRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = !", !strconcat(opc , "($src1, $src2)")), + [(set PredRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class qi_neg_ALU32_sis10<string opc, Intrinsic IntID> + : ALU32_rr<(outs PredRegs:$dst), (ins IntRegs:$src1, s10Imm:$src2), + !strconcat("$dst = !", !strconcat(opc , "($src1, #$src2)")), + [(set PredRegs:$dst, (IntID IntRegs:$src1, imm:$src2))]>; + +class qi_neg_ALU32_siu9<string opc, Intrinsic IntID> + : ALU32_rr<(outs PredRegs:$dst), (ins IntRegs:$src1, u9Imm:$src2), + !strconcat("$dst = !", !strconcat(opc , "($src1, #$src2)")), + [(set PredRegs:$dst, (IntID IntRegs:$src1, imm:$src2))]>; + +class si_neg_ALU32_sisi<string opc, Intrinsic IntID> + : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = !", !strconcat(opc , "($src1, $src2)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class si_neg_ALU32_sis8<string opc, Intrinsic IntID> + : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, s8Imm:$src2), + !strconcat("$dst = !", !strconcat(opc , "($src1, #$src2)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, imm:$src2))]>; + +class si_ALU32_sis8<string opc, Intrinsic IntID> + : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, s8Imm:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, #$src2)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, imm:$src2))]>; + + +// +// SInst Classes. +// +class qi_neg_SInst_qiqi<string opc, Intrinsic IntID> + : SInst<(outs PredRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2), + !strconcat("$dst = !", !strconcat(opc , "($src1, $src2)")), + [(set PredRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>; + +class qi_SInst_qi_andqiqi_neg<string opc, Intrinsic IntID> + : SInst<(outs PredRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2, + IntRegs:$src3), + !strconcat("$dst = ", !strconcat(opc , + "($src1, and($src2, !$src3)")), + [(set PredRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2, + IntRegs:$src3))]>; + +class qi_SInst_qi_andqiqi<string opc, Intrinsic IntID> + : SInst<(outs PredRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2, + IntRegs:$src3), + !strconcat("$dst = ", !strconcat(opc , + "($src1, and($src2, $src3)")), + [(set PredRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2, + IntRegs:$src3))]>; + +class qi_SInst_qi_orqiqi_neg<string opc, Intrinsic IntID> + : SInst<(outs PredRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2, + IntRegs:$src3), + !strconcat("$dst = ", !strconcat(opc , + "($src1, or($src2, !$src3)")), + [(set PredRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2, + IntRegs:$src3))]>; + +class qi_SInst_qi_orqiqi<string opc, Intrinsic IntID> + : SInst<(outs PredRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2, + IntRegs:$src3), + !strconcat("$dst = ", !strconcat(opc , + "($src1, or($src2, $src3)")), + [(set PredRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2, + IntRegs:$src3))]>; + +class si_SInst_si_addsis6<string opc, Intrinsic IntID> + : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2, s6Imm:$src3), + !strconcat("$dst = ", !strconcat(opc , + "($src1, add($src2, #$src3)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2, + imm:$src3))]>; + +class si_SInst_si_subs6si<string opc, Intrinsic IntID> + : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, s6Imm:$src2, IntRegs:$src3), + !strconcat("$dst = ", !strconcat(opc , + "($src1, sub(#$src2, $src3)")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, imm:$src2, + IntRegs:$src3))]>; + +class di_ALU64_didi_neg<string opc, Intrinsic IntID> + : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, ~$src2)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$src1, DoubleRegs:$src2))]>; + +class di_MInst_dididi_xacc<string opc, Intrinsic IntID> + : MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, DoubleRegs:$src1, + DoubleRegs:$src2), + !strconcat("$dst ^= ", !strconcat(opc , "($src1, $src2)")), + [(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, DoubleRegs:$src1, + DoubleRegs:$src2))], + "$dst2 = $dst">; + +class si_MInst_sisisi_and<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$dst1, IntRegs:$src2, + IntRegs:$src3), + !strconcat("$dst &= ", !strconcat(opc , "($src2, $src3)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst1, IntRegs:$src2, + IntRegs:$src3))]>; + +class si_MInst_sisisi_andn<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$dst1, IntRegs:$src2, + IntRegs:$src3), + !strconcat("$dst &= ", !strconcat(opc , "($src2, ~$src3)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst1, IntRegs:$src2, + IntRegs:$src3))]>; + +class si_SInst_sisis10_andi<string opc, Intrinsic IntID> + : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2, s10Imm:$src3), + !strconcat("$dst = ", !strconcat(opc , + "($src1, and($src2, #$src3))")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2, + imm:$src3))]>; + +class si_MInst_sisisi_xor<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$dst1, IntRegs:$src2, + IntRegs:$src3), + !strconcat("$dst ^= ", !strconcat(opc , "($src2, $src3)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst1, IntRegs:$src2, + IntRegs:$src3))]>; + +class si_MInst_sisisi_xorn<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$dst1, IntRegs:$src2, + IntRegs:$src3), + !strconcat("$dst ^= ", !strconcat(opc , "($src2, ~$src3)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst1, IntRegs:$src2, + IntRegs:$src3))]>; + +class si_SInst_sisis10_or<string opc, Intrinsic IntID> + : SInst<(outs IntRegs:$dst), (ins IntRegs:$dst1, IntRegs:$src2, s10Imm:$src3), + !strconcat("$dst |= ", !strconcat(opc , "($src2, #$src3)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst1, IntRegs:$src2, + imm:$src3))]>; + +class si_MInst_sisisi_or<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$dst1, IntRegs:$src2, + IntRegs:$src3), + !strconcat("$dst |= ", !strconcat(opc , "($src2, $src3)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst1, IntRegs:$src2, + IntRegs:$src3))]>; + +class si_MInst_sisisi_orn<string opc, Intrinsic IntID> + : MInst<(outs IntRegs:$dst), (ins IntRegs:$dst1, IntRegs:$src2, + IntRegs:$src3), + !strconcat("$dst |= ", !strconcat(opc , "($src2, ~$src3)")), + [(set IntRegs:$dst, (IntID IntRegs:$dst1, IntRegs:$src2, + IntRegs:$src3))]>; + +class si_SInst_siu5_sat<string opc, Intrinsic IntID> + : SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2), + !strconcat("$dst = ", !strconcat(opc , "($src1, #$src2):sat")), + [(set IntRegs:$dst, (IntID IntRegs:$src1, imm:$src2))]>; + + +/******************************************************************** +* ALU32/ALU * +*********************************************************************/ + +// ALU32 / ALU / Logical Operations. +def Hexagon_A4_orn : si_ALU32_sisi_not <"or", int_hexagon_A4_orn>; +def Hexagon_A4_andn : si_ALU32_sisi_not <"and", int_hexagon_A4_andn>; + + +/******************************************************************** +* ALU32/PERM * +*********************************************************************/ + +// ALU32 / PERM / Combine Words Into Doublewords. +def Hexagon_A4_combineir : di_ALU32_s8si <"combine", int_hexagon_A4_combineir>; +def Hexagon_A4_combineri : di_ALU32_sis8 <"combine", int_hexagon_A4_combineri>; + + +/******************************************************************** +* ALU32/PRED * +*********************************************************************/ + +// ALU32 / PRED / Conditional Shift Halfword. +// ALU32 / PRED / Conditional Sign Extend. +// ALU32 / PRED / Conditional Zero Extend. +// ALU32 / PRED / Compare. +def Hexagon_C4_cmpneq : qi_neg_ALU32_sisi <"cmp.eq", int_hexagon_C4_cmpneq>; +def Hexagon_C4_cmpneqi : qi_neg_ALU32_sis10 <"cmp.eq", int_hexagon_C4_cmpneqi>; +def Hexagon_C4_cmplte : qi_neg_ALU32_sisi <"cmp.gt", int_hexagon_C4_cmplte>; +def Hexagon_C4_cmpltei : qi_neg_ALU32_sis10 <"cmp.gt", int_hexagon_C4_cmpltei>; +def Hexagon_C4_cmplteu : qi_neg_ALU32_sisi <"cmp.gtu",int_hexagon_C4_cmplteu>; +def Hexagon_C4_cmplteui: qi_neg_ALU32_siu9 <"cmp.gtu",int_hexagon_C4_cmplteui>; + +// ALU32 / PRED / cmpare To General Register. +def Hexagon_A4_rcmpneq : si_neg_ALU32_sisi <"cmp.eq", int_hexagon_A4_rcmpneq>; +def Hexagon_A4_rcmpneqi: si_neg_ALU32_sis8 <"cmp.eq", int_hexagon_A4_rcmpneqi>; +def Hexagon_A4_rcmpeq : si_ALU32_sisi <"cmp.eq", int_hexagon_A4_rcmpeq>; +def Hexagon_A4_rcmpeqi : si_ALU32_sis8 <"cmp.eq", int_hexagon_A4_rcmpeqi>; + + +/******************************************************************** +* CR * +*********************************************************************/ + +// CR / Corner Detection Acceleration. +def Hexagon_C4_fastcorner9: + qi_SInst_qiqi<"fastcorner9", int_hexagon_C4_fastcorner9>; +def Hexagon_C4_fastcorner9_not: + qi_neg_SInst_qiqi<"fastcorner9",int_hexagon_C4_fastcorner9_not>; + +// CR / Logical Operations On Predicates. +def Hexagon_C4_and_andn: + qi_SInst_qi_andqiqi_neg <"and", int_hexagon_C4_and_andn>; +def Hexagon_C4_and_and: + qi_SInst_qi_andqiqi <"and", int_hexagon_C4_and_and>; +def Hexagon_C4_and_orn: + qi_SInst_qi_orqiqi_neg <"and", int_hexagon_C4_and_orn>; +def Hexagon_C4_and_or: + qi_SInst_qi_orqiqi <"and", int_hexagon_C4_and_or>; +def Hexagon_C4_or_andn: + qi_SInst_qi_andqiqi_neg <"or", int_hexagon_C4_or_andn>; +def Hexagon_C4_or_and: + qi_SInst_qi_andqiqi <"or", int_hexagon_C4_or_and>; +def Hexagon_C4_or_orn: + qi_SInst_qi_orqiqi_neg <"or", int_hexagon_C4_or_orn>; +def Hexagon_C4_or_or: + qi_SInst_qi_orqiqi <"or", int_hexagon_C4_or_or>; + + +/******************************************************************** +* XTYPE/ALU * +*********************************************************************/ + +// XTYPE / ALU / Add And Accumulate. +def Hexagon_S4_addaddi: + si_SInst_si_addsis6 <"add", int_hexagon_S4_addaddi>; +def Hexagon_S4_subaddi: + si_SInst_si_subs6si <"add", int_hexagon_S4_subaddi>; + +// XTYPE / ALU / Logical Doublewords. +def Hexagon_S4_andnp: + di_ALU64_didi_neg <"and", int_hexagon_A4_andnp>; +def Hexagon_S4_ornp: + di_ALU64_didi_neg <"or", int_hexagon_A4_ornp>; + +// XTYPE / ALU / Logical-logical Doublewords. +def Hexagon_M4_xor_xacc: + di_MInst_dididi_xacc <"xor", int_hexagon_M4_xor_xacc>; + +// XTYPE / ALU / Logical-logical Words. +def HEXAGON_M4_and_and: + si_MInst_sisisi_and <"and", int_hexagon_M4_and_and>; +def HEXAGON_M4_and_or: + si_MInst_sisisi_and <"or", int_hexagon_M4_and_or>; +def HEXAGON_M4_and_xor: + si_MInst_sisisi_and <"xor", int_hexagon_M4_and_xor>; +def HEXAGON_M4_and_andn: + si_MInst_sisisi_andn <"and", int_hexagon_M4_and_andn>; +def HEXAGON_M4_xor_and: + si_MInst_sisisi_xor <"and", int_hexagon_M4_xor_and>; +def HEXAGON_M4_xor_or: + si_MInst_sisisi_xor <"or", int_hexagon_M4_xor_or>; +def HEXAGON_M4_xor_andn: + si_MInst_sisisi_xorn <"and", int_hexagon_M4_xor_andn>; +def HEXAGON_M4_or_and: + si_MInst_sisisi_or <"and", int_hexagon_M4_or_and>; +def HEXAGON_M4_or_or: + si_MInst_sisisi_or <"or", int_hexagon_M4_or_or>; +def HEXAGON_M4_or_xor: + si_MInst_sisisi_or <"xor", int_hexagon_M4_or_xor>; +def HEXAGON_M4_or_andn: + si_MInst_sisisi_orn <"and", int_hexagon_M4_or_andn>; +def HEXAGON_S4_or_andix: + si_SInst_sisis10_andi <"or", int_hexagon_S4_or_andix>; +def HEXAGON_S4_or_andi: + si_SInst_sisis10_or <"and", int_hexagon_S4_or_andi>; +def HEXAGON_S4_or_ori: + si_SInst_sisis10_or <"or", int_hexagon_S4_or_ori>; + +// XTYPE / ALU / Modulo wrap. +def HEXAGON_A4_modwrapu: + si_ALU64_sisi <"modwrap", int_hexagon_A4_modwrapu>; + +// XTYPE / ALU / Round. +def HEXAGON_A4_cround_ri: + si_SInst_siu5 <"cround", int_hexagon_A4_cround_ri>; +def HEXAGON_A4_cround_rr: + si_SInst_sisi <"cround", int_hexagon_A4_cround_rr>; +def HEXAGON_A4_round_ri: + si_SInst_siu5 <"round", int_hexagon_A4_round_ri>; +def HEXAGON_A4_round_rr: + si_SInst_sisi <"round", int_hexagon_A4_round_rr>; +def HEXAGON_A4_round_ri_sat: + si_SInst_siu5_sat <"round", int_hexagon_A4_round_ri_sat>; +def HEXAGON_A4_round_rr_sat: + si_SInst_sisi_sat <"round", int_hexagon_A4_round_rr_sat>; + +// XTYPE / ALU / Vector reduce add unsigned halfwords. +// XTYPE / ALU / Vector add bytes. +// XTYPE / ALU / Vector conditional negate. +// XTYPE / ALU / Vector maximum bytes. +// XTYPE / ALU / Vector reduce maximum halfwords. +// XTYPE / ALU / Vector reduce maximum words. +// XTYPE / ALU / Vector minimum bytes. +// XTYPE / ALU / Vector reduce minimum halfwords. +// XTYPE / ALU / Vector reduce minimum words. +// XTYPE / ALU / Vector subtract bytes. + + +/******************************************************************** +* XTYPE/BIT * +*********************************************************************/ + +// XTYPE / BIT / Count leading. +// XTYPE / BIT / Count trailing. +// XTYPE / BIT / Extract bitfield. +// XTYPE / BIT / Masked parity. +// XTYPE / BIT / Bit reverse. +// XTYPE / BIT / Split bitfield. + + +/******************************************************************** +* XTYPE/COMPLEX * +*********************************************************************/ + +// XTYPE / COMPLEX / Complex add/sub halfwords. +// XTYPE / COMPLEX / Complex add/sub words. +// XTYPE / COMPLEX / Complex multiply 32x16. +// XTYPE / COMPLEX / Vector reduce complex rotate. + + +/******************************************************************** +* XTYPE/MPY * +*********************************************************************/ + +// XTYPE / COMPLEX / Complex add/sub halfwords. diff --git a/lib/Target/Hexagon/HexagonMCAsmInfo.cpp b/lib/Target/Hexagon/HexagonMCAsmInfo.cpp new file mode 100644 index 0000000000..188693cf63 --- /dev/null +++ b/lib/Target/Hexagon/HexagonMCAsmInfo.cpp @@ -0,0 +1,36 @@ +//===-- HexagonMCAsmInfo.cpp - Hexagon asm properties -----------*- 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 the declarations of the HexagonMCAsmInfo properties. +// +//===----------------------------------------------------------------------===// + +#include "HexagonMCAsmInfo.h" + +using namespace llvm; + +HexagonMCAsmInfo::HexagonMCAsmInfo(const Target &T, StringRef TT) { + Data16bitsDirective = "\t.half\t"; + Data32bitsDirective = "\t.word\t"; + Data64bitsDirective = 0; // .xword is only supported by V9. + ZeroDirective = "\t.skip\t"; + CommentString = "//"; + HasLEB128 = true; + + PrivateGlobalPrefix = ".L"; + LCOMMDirectiveType = LCOMM::ByteAlignment; + InlineAsmStart = "# InlineAsm Start"; + InlineAsmEnd = "# InlineAsm End"; + ZeroDirective = "\t.space\t"; + AscizDirective = "\t.string\t"; + WeakRefDirective = "\t.weak\t"; + + UsesELFSectionDirectiveForBSS = true; + ExceptionsType = ExceptionHandling::DwarfCFI; +} diff --git a/lib/Target/Hexagon/HexagonMCAsmInfo.h b/lib/Target/Hexagon/HexagonMCAsmInfo.h new file mode 100644 index 0000000000..8196e956f7 --- /dev/null +++ b/lib/Target/Hexagon/HexagonMCAsmInfo.h @@ -0,0 +1,30 @@ +//===-- HexagonTargetAsmInfo.h - Hexagon asm properties ---------*- 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 the declaration of the HexagonMCAsmInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef HexagonMCASMINFO_H +#define HexagonMCASMINFO_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCAsmInfo.h" + +namespace llvm { + class Target; + + class HexagonMCAsmInfo : public MCAsmInfo { + public: + explicit HexagonMCAsmInfo(const Target &T, StringRef TT); + }; + +} // namespace llvm + +#endif diff --git a/lib/Target/Hexagon/HexagonMachineFunctionInfo.h b/lib/Target/Hexagon/HexagonMachineFunctionInfo.h new file mode 100644 index 0000000000..0318c519e4 --- /dev/null +++ b/lib/Target/Hexagon/HexagonMachineFunctionInfo.h @@ -0,0 +1,75 @@ +//=- HexagonMachineFuctionInfo.h - Hexagon machine function info --*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef HexagonMACHINEFUNCTIONINFO_H +#define HexagonMACHINEFUNCTIONINFO_H + +#include "llvm/CodeGen/MachineFunction.h" + +namespace llvm { + + namespace Hexagon { + const unsigned int StartPacket = 0x1; + const unsigned int EndPacket = 0x2; + } + + +/// Hexagon target-specific information for each MachineFunction. +class HexagonMachineFunctionInfo : public MachineFunctionInfo { + // SRetReturnReg - Some subtargets require that sret lowering includes + // returning the value of the returned struct in a register. This field + // holds the virtual register into which the sret argument is passed. + unsigned SRetReturnReg; + std::vector<MachineInstr*> AllocaAdjustInsts; + int VarArgsFrameIndex; + bool HasClobberLR; + + std::map<const MachineInstr*, unsigned> PacketInfo; + + +public: + HexagonMachineFunctionInfo() : SRetReturnReg(0), HasClobberLR(0) {} + + HexagonMachineFunctionInfo(MachineFunction &MF) : SRetReturnReg(0), + HasClobberLR(0) {} + + unsigned getSRetReturnReg() const { return SRetReturnReg; } + void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; } + + void addAllocaAdjustInst(MachineInstr* MI) { + AllocaAdjustInsts.push_back(MI); + } + const std::vector<MachineInstr*>& getAllocaAdjustInsts() { + return AllocaAdjustInsts; + } + + void setVarArgsFrameIndex(int v) { VarArgsFrameIndex = v; } + int getVarArgsFrameIndex() { return VarArgsFrameIndex; } + + void setStartPacket(MachineInstr* MI) { + PacketInfo[MI] |= Hexagon::StartPacket; + } + void setEndPacket(MachineInstr* MI) { + PacketInfo[MI] |= Hexagon::EndPacket; + } + bool isStartPacket(const MachineInstr* MI) const { + return (PacketInfo.count(MI) && + (PacketInfo.find(MI)->second & Hexagon::StartPacket)); + } + bool isEndPacket(const MachineInstr* MI) const { + return (PacketInfo.count(MI) && + (PacketInfo.find(MI)->second & Hexagon::EndPacket)); + } + void setHasClobberLR(bool v) { HasClobberLR = v; } + bool hasClobberLR() const { return HasClobberLR; } + +}; +} // End llvm namespace + +#endif diff --git a/lib/Target/Hexagon/HexagonOptimizeSZExtends.cpp b/lib/Target/Hexagon/HexagonOptimizeSZExtends.cpp new file mode 100644 index 0000000000..1229aca58e --- /dev/null +++ b/lib/Target/Hexagon/HexagonOptimizeSZExtends.cpp @@ -0,0 +1,129 @@ +//===-- HexagonOptimizeSZExtends.cpp - Identify and remove sign and -------===// +//===-- zero extends. -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Constants.h" +#include "llvm/PassSupport.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/Support/Debug.h" +#include "llvm/CodeGen/MachineFunctionAnalysis.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetInstrInfo.h" +#include <algorithm> +#include "Hexagon.h" +#include "HexagonTargetMachine.h" + +using namespace llvm; + +namespace { + struct HexagonOptimizeSZExtends : public MachineFunctionPass { + + public: + static char ID; + HexagonOptimizeSZExtends() : MachineFunctionPass(ID) {} + + bool runOnMachineFunction(MachineFunction &MF); + + const char *getPassName() const { + return "Hexagon remove redundant zero and size extends"; + } + + void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired<MachineFunctionAnalysis>(); + AU.addPreserved<MachineFunctionAnalysis>(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + private: + }; +} + +char HexagonOptimizeSZExtends::ID = 0; + +// This is a brain dead pass to get rid of redundant sign extends for the +// following case: +// +// Transform the following pattern +// %vreg170<def> = SXTW %vreg166 +// ... +// %vreg176<def> = COPY %vreg170:subreg_loreg +// +// Into +// %vreg176<def> = COPY vreg166 + +bool HexagonOptimizeSZExtends::runOnMachineFunction(MachineFunction &MF) { + DenseMap<unsigned, unsigned> SExtMap; + + // Loop over all of the basic blocks + for (MachineFunction::iterator MBBb = MF.begin(), MBBe = MF.end(); + MBBb != MBBe; ++MBBb) { + MachineBasicBlock* MBB = MBBb; + SExtMap.clear(); + + // Traverse the basic block. + for (MachineBasicBlock::iterator MII = MBB->begin(); MII != MBB->end(); + ++MII) { + MachineInstr *MI = MII; + // Look for sign extends: + // %vreg170<def> = SXTW %vreg166 + if (MI->getOpcode() == Hexagon::SXTW) { + assert (MI->getNumOperands() == 2); + MachineOperand &Dst = MI->getOperand(0); + MachineOperand &Src = MI->getOperand(1); + unsigned DstReg = Dst.getReg(); + unsigned SrcReg = Src.getReg(); + // Just handle virtual registers. + if (TargetRegisterInfo::isVirtualRegister(DstReg) && + TargetRegisterInfo::isVirtualRegister(SrcReg)) { + // Map the following: + // %vreg170<def> = SXTW %vreg166 + // SExtMap[170] = vreg166 + SExtMap[DstReg] = SrcReg; + } + } + // Look for copy: + // %vreg176<def> = COPY %vreg170:subreg_loreg + if (MI->isCopy()) { + assert (MI->getNumOperands() == 2); + MachineOperand &Dst = MI->getOperand(0); + MachineOperand &Src = MI->getOperand(1); + + // Make sure we are copying the lower 32 bits. + if (Src.getSubReg() != Hexagon::subreg_loreg) + continue; + + unsigned DstReg = Dst.getReg(); + unsigned SrcReg = Src.getReg(); + if (TargetRegisterInfo::isVirtualRegister(DstReg) && + TargetRegisterInfo::isVirtualRegister(SrcReg)) { + // Try to find in the map. + if (unsigned SextSrc = SExtMap.lookup(SrcReg)) { + // Change the 1st operand. + MI->RemoveOperand(1); + MI->addOperand(MachineOperand::CreateReg(SextSrc, false)); + } + } + } + } + } + return true; +} + +FunctionPass *llvm::createHexagonOptimizeSZExtends() { + return new HexagonOptimizeSZExtends(); +} diff --git a/lib/Target/Hexagon/HexagonRegisterInfo.cpp b/lib/Target/Hexagon/HexagonRegisterInfo.cpp new file mode 100644 index 0000000000..9fd9fd3424 --- /dev/null +++ b/lib/Target/Hexagon/HexagonRegisterInfo.cpp @@ -0,0 +1,322 @@ +//==- HexagonRegisterInfo.cpp - Hexagon Register Information -----*- 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 the Hexagon implementation of the TargetRegisterInfo +// class. +// +//===----------------------------------------------------------------------===// + +#include "Hexagon.h" +#include "HexagonRegisterInfo.h" +#include "HexagonSubtarget.h" +#include "HexagonTargetMachine.h" +#include "HexagonMachineFunctionInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/MC/MachineLocation.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Type.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include <iostream> + +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Function.h" +using namespace llvm; + + +HexagonRegisterInfo::HexagonRegisterInfo(HexagonSubtarget &st, + const HexagonInstrInfo &tii) + : HexagonGenRegisterInfo(Hexagon::R31), + Subtarget(st), + TII(tii) { +} + +const unsigned* HexagonRegisterInfo::getCalleeSavedRegs(const MachineFunction + *MF) + const { + static const unsigned CalleeSavedRegsV2[] = { + Hexagon::R24, Hexagon::R25, Hexagon::R26, Hexagon::R27, 0 + }; + static const unsigned CalleeSavedRegsV3[] = { + Hexagon::R16, Hexagon::R17, Hexagon::R18, Hexagon::R19, + Hexagon::R20, Hexagon::R21, Hexagon::R22, Hexagon::R23, + Hexagon::R24, Hexagon::R25, Hexagon::R26, Hexagon::R27, 0 + }; + + switch(Subtarget.getHexagonArchVersion()) { + case HexagonSubtarget::V2: + return CalleeSavedRegsV2; + break; + case HexagonSubtarget::V3: + case HexagonSubtarget::V4: + return CalleeSavedRegsV3; + break; + default: + const char *ErrorString = + "Callee saved registers requested for unknown archtecture version"; + llvm_unreachable(ErrorString); + } +} + +BitVector HexagonRegisterInfo::getReservedRegs(const MachineFunction &MF) + const { + BitVector Reserved(getNumRegs()); + Reserved.set(HEXAGON_RESERVED_REG_1); + Reserved.set(HEXAGON_RESERVED_REG_2); + Reserved.set(Hexagon::R29); + Reserved.set(Hexagon::R30); + Reserved.set(Hexagon::R31); + Reserved.set(Hexagon::D14); + Reserved.set(Hexagon::D15); + Reserved.set(Hexagon::LC0); + Reserved.set(Hexagon::LC1); + Reserved.set(Hexagon::SA0); + Reserved.set(Hexagon::SA1); + return Reserved; +} + + +const TargetRegisterClass* const* +HexagonRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const { + static const TargetRegisterClass * const CalleeSavedRegClassesV2[] = { + &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, + &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, + }; + static const TargetRegisterClass * const CalleeSavedRegClassesV3[] = { + &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, + &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, + &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, + &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, + &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, + &Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass, + }; + + switch(Subtarget.getHexagonArchVersion()) { + case HexagonSubtarget::V2: + return CalleeSavedRegClassesV2; + break; + case HexagonSubtarget::V3: + case HexagonSubtarget::V4: + return CalleeSavedRegClassesV3; + break; + default: + const char *ErrorString = + "Callee saved register classes requested for unknown archtecture version"; + llvm_unreachable(ErrorString); + } +} + +void HexagonRegisterInfo:: +eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { + MachineInstr &MI = *I; + + if (MI.getOpcode() == Hexagon::ADJCALLSTACKDOWN) { + // Hexagon_TODO: add code + } else if (MI.getOpcode() == Hexagon::ADJCALLSTACKUP) { + // Hexagon_TODO: add code + } else { + assert(0 && "Cannot handle this call frame pseudo instruction"); + } + MBB.erase(I); +} + +void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, RegScavenger *RS) const { + + // + // Hexagon_TODO: Do we need to enforce this for Hexagon? + assert(SPAdj == 0 && "Unexpected"); + + + unsigned i = 0; + MachineInstr &MI = *II; + while (!MI.getOperand(i).isFI()) { + ++i; + assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); + } + + int FrameIndex = MI.getOperand(i).getIndex(); + + // Addressable stack objects are accessed using neg. offsets from %fp. + MachineFunction &MF = *MI.getParent()->getParent(); + int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex); + MachineFrameInfo &MFI = *MF.getFrameInfo(); + + unsigned FrameReg = getFrameRegister(MF); + const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); + if (!TFI->hasFP(MF)) { + // We will not reserve space on the stack for the lr and fp registers. + Offset -= 2 * Hexagon_WordSize; + } + + const unsigned FrameSize = MFI.getStackSize(); + + if (!MFI.hasVarSizedObjects() && + TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset)) && + !TII.isSpillPredRegOp(&MI)) { + // Replace frame index with a stack pointer reference. + MI.getOperand(i).ChangeToRegister(getStackRegister(), false, false, true); + MI.getOperand(i+1).ChangeToImmediate(FrameSize+Offset); + } else { + // Replace frame index with a frame pointer reference. + if (!TII.isValidOffset(MI.getOpcode(), Offset)) { + + // If the offset overflows, then correct it. + // + // For loads, we do not need a reserved register + // r0 = memw(r30 + #10000) to: + // + // r0 = add(r30, #10000) + // r0 = memw(r0) + if ( (MI.getOpcode() == Hexagon::LDriw) || + (MI.getOpcode() == Hexagon::LDrid) || + (MI.getOpcode() == Hexagon::LDrih) || + (MI.getOpcode() == Hexagon::LDriuh) || + (MI.getOpcode() == Hexagon::LDrib) || + (MI.getOpcode() == Hexagon::LDriub) ) { + unsigned dstReg = (MI.getOpcode() == Hexagon::LDrid) ? + *getSubRegisters(MI.getOperand(0).getReg()) : + MI.getOperand(0).getReg(); + + // Check if offset can fit in addi. + if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) { + BuildMI(*MI.getParent(), II, MI.getDebugLoc(), + TII.get(Hexagon::CONST32_Int_Real), dstReg).addImm(Offset); + BuildMI(*MI.getParent(), II, MI.getDebugLoc(), + TII.get(Hexagon::ADD_rr), + dstReg).addReg(FrameReg).addReg(dstReg); + } else { + BuildMI(*MI.getParent(), II, MI.getDebugLoc(), + TII.get(Hexagon::ADD_ri), + dstReg).addReg(FrameReg).addImm(Offset); + } + + MI.getOperand(i).ChangeToRegister(dstReg, false, false, true); + MI.getOperand(i+1).ChangeToImmediate(0); + } else if ((MI.getOpcode() == Hexagon::STriw) || + (MI.getOpcode() == Hexagon::STrid) || + (MI.getOpcode() == Hexagon::STrih) || + (MI.getOpcode() == Hexagon::STrib) || + (MI.getOpcode() == Hexagon::STriwt)) { + // For stores, we need a reserved register. Change + // memw(r30 + #10000) = r0 to: + // + // rs = add(r30, #10000); + // memw(rs) = r0 + unsigned resReg = HEXAGON_RESERVED_REG_1; + + // Check if offset can fit in addi. + if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) { + BuildMI(*MI.getParent(), II, MI.getDebugLoc(), + TII.get(Hexagon::CONST32_Int_Real), resReg).addImm(Offset); + BuildMI(*MI.getParent(), II, MI.getDebugLoc(), + TII.get(Hexagon::ADD_rr), + resReg).addReg(FrameReg).addReg(resReg); + } else { + BuildMI(*MI.getParent(), II, MI.getDebugLoc(), + TII.get(Hexagon::ADD_ri), + resReg).addReg(FrameReg).addImm(Offset); + } + MI.getOperand(i).ChangeToRegister(resReg, false, false, true); + MI.getOperand(i+1).ChangeToImmediate(0); + } else if (TII.isMemOp(&MI)) { + unsigned resReg = HEXAGON_RESERVED_REG_1; + if (!MFI.hasVarSizedObjects() && + TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset))) { + MI.getOperand(i).ChangeToRegister(getStackRegister(), false, false, + true); + MI.getOperand(i+1).ChangeToImmediate(FrameSize+Offset); + } else if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) { + BuildMI(*MI.getParent(), II, MI.getDebugLoc(), + TII.get(Hexagon::CONST32_Int_Real), resReg).addImm(Offset); + BuildMI(*MI.getParent(), II, MI.getDebugLoc(), + TII.get(Hexagon::ADD_rr), + resReg).addReg(FrameReg).addReg(resReg); + MI.getOperand(i).ChangeToRegister(resReg, false, false, true); + MI.getOperand(i+1).ChangeToImmediate(0); + } else { + BuildMI(*MI.getParent(), II, MI.getDebugLoc(), + TII.get(Hexagon::ADD_ri), + resReg).addReg(FrameReg).addImm(Offset); + MI.getOperand(i).ChangeToRegister(resReg, false, false, true); + MI.getOperand(i+1).ChangeToImmediate(0); + } + } else { + unsigned dstReg = MI.getOperand(0).getReg(); + BuildMI(*MI.getParent(), II, MI.getDebugLoc(), + TII.get(Hexagon::CONST32_Int_Real), dstReg).addImm(Offset); + BuildMI(*MI.getParent(), II, MI.getDebugLoc(), + TII.get(Hexagon::ADD_rr), + dstReg).addReg(FrameReg).addReg(dstReg); + // Can we delete MI??? r2 = add (r2, #0). + MI.getOperand(i).ChangeToRegister(dstReg, false, false, true); + MI.getOperand(i+1).ChangeToImmediate(0); + } + } else { + // If the offset is small enough to fit in the immediate field, directly + // encode it. + MI.getOperand(i).ChangeToRegister(FrameReg, false); + MI.getOperand(i+1).ChangeToImmediate(Offset); + } + } + +} + +unsigned HexagonRegisterInfo::getRARegister() const { + return Hexagon::R31; +} + +unsigned HexagonRegisterInfo::getFrameRegister(const MachineFunction + &MF) const { + const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); + if (TFI->hasFP(MF)) { + return Hexagon::R30; + } + + return Hexagon::R29; +} + +unsigned HexagonRegisterInfo::getFrameRegister() const { + return Hexagon::R30; +} + +unsigned HexagonRegisterInfo::getStackRegister() const { + return Hexagon::R29; +} + +void HexagonRegisterInfo::getInitialFrameState(std::vector<MachineMove> + &Moves) const +{ + // VirtualFP = (R30 + #0). + unsigned FPReg = getFrameRegister(); + MachineLocation Dst(MachineLocation::VirtualFP); + MachineLocation Src(FPReg, 0); + Moves.push_back(MachineMove(0, Dst, Src)); +} + +unsigned HexagonRegisterInfo::getEHExceptionRegister() const { + assert(0 && "What is the exception register"); + return 0; +} + +unsigned HexagonRegisterInfo::getEHHandlerRegister() const { + assert(0 && "What is the exception handler register"); + return 0; +} + +#include "HexagonGenRegisterInfo.inc" diff --git a/lib/Target/Hexagon/HexagonRegisterInfo.h b/lib/Target/Hexagon/HexagonRegisterInfo.h new file mode 100644 index 0000000000..33b0c14453 --- /dev/null +++ b/lib/Target/Hexagon/HexagonRegisterInfo.h @@ -0,0 +1,89 @@ +//==- HexagonRegisterInfo.h - Hexagon Register Information Impl --*- 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 the Hexagon implementation of the TargetRegisterInfo +// class. +// +//===----------------------------------------------------------------------===// + +#ifndef HexagonREGISTERINFO_H +#define HexagonREGISTERINFO_H + +#include "llvm/Target/TargetRegisterInfo.h" +#define GET_REGINFO_HEADER +#include "HexagonGenRegisterInfo.inc" +#include "llvm/MC/MachineLocation.h" + +// +// We try not to hard code the reserved registers in our code, +// so the following two macros were defined. However, there +// are still a few places that R11 and R10 are hard wired. +// See below. If, in the future, we decided to change the reserved +// register. Don't forget changing the following places. +// +// 1. the "Defs" set of STriw_pred in HexagonInstrInfo.td +// 2. the "Defs" set of LDri_pred in HexagonInstrInfo.td +// 3. the definition of "IntRegs" in HexagonRegisterInfo.td +// 4. the definition of "DoubleRegs" in HexagonRegisterInfo.td +// +#define HEXAGON_RESERVED_REG_1 Hexagon::R10 +#define HEXAGON_RESERVED_REG_2 Hexagon::R11 + +namespace llvm { + +class HexagonSubtarget; +class HexagonInstrInfo; +class Type; + +struct HexagonRegisterInfo : public HexagonGenRegisterInfo { + HexagonSubtarget &Subtarget; + const HexagonInstrInfo &TII; + + HexagonRegisterInfo(HexagonSubtarget &st, const HexagonInstrInfo &tii); + + /// Code Generation virtual methods... + const unsigned *getCalleeSavedRegs(const MachineFunction *MF = 0) const; + + const TargetRegisterClass* const* getCalleeSavedRegClasses( + const MachineFunction *MF = 0) const; + + BitVector getReservedRegs(const MachineFunction &MF) const; + + void eliminateCallFramePseudoInstr(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const; + + void eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, RegScavenger *RS = NULL) const; + + /// determineFrameLayout - Determine the size of the frame and maximum call + /// frame size. + void determineFrameLayout(MachineFunction &MF) const; + + /// requiresRegisterScavenging - returns true since we may need scavenging for + /// a temporary register when generating hardware loop instructions. + bool requiresRegisterScavenging(const MachineFunction &MF) const { + return true; + } + + // Debug information queries. + unsigned getRARegister() const; + unsigned getFrameRegister(const MachineFunction &MF) const; + unsigned getFrameRegister() const; + void getInitialFrameState(std::vector<MachineMove> &Moves) const; + unsigned getStackRegister() const; + + // Exception handling queries. + unsigned getEHExceptionRegister() const; + unsigned getEHHandlerRegister() const; +}; + +} // end namespace llvm + +#endif diff --git a/lib/Target/Hexagon/HexagonRegisterInfo.td b/lib/Target/Hexagon/HexagonRegisterInfo.td new file mode 100644 index 0000000000..c05f844556 --- /dev/null +++ b/lib/Target/Hexagon/HexagonRegisterInfo.td @@ -0,0 +1,169 @@ +//===- HexagonRegisterInfo.td - Hexagon Register defs ------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Declarations that describe the Hexagon register file. +//===----------------------------------------------------------------------===// + +class HexagonReg<string n> : Register<n> { + field bits<5> Num; + let Namespace = "Hexagon"; +} + +class HexagonDoubleReg<string n, list<Register> subregs> : + RegisterWithSubRegs<n, subregs> { + field bits<5> Num; + let Namespace = "Hexagon"; +} + +// Registers are identified with 5-bit ID numbers. +// Ri - 32-bit integer registers. +class Ri<bits<5> num, string n> : HexagonReg<n> { + let Num = num; +} + +// Rf - 32-bit floating-point registers. +class Rf<bits<5> num, string n> : HexagonReg<n> { + let Num = num; +} + + +// Rd - 64 bit registers. +class Rd<bits<5> num, string n, list<Register> subregs> : +HexagonDoubleReg<n, subregs> { + let Num = num; + let SubRegs = subregs; +} + + +class Rp<bits<5> num, string n> : HexagonReg<n> { + let Num = num; +} + +class Rc<bits<5> num, string n> : HexagonReg<n> { + let Num = num; +} + +let Namespace = "Hexagon" in { + + def subreg_loreg : SubRegIndex; + def subreg_hireg : SubRegIndex; + + // Integer registers. + def R0 : Ri< 0, "r0">, DwarfRegNum<[0]>; + def R1 : Ri< 1, "r1">, DwarfRegNum<[1]>; + def R2 : Ri< 2, "r2">, DwarfRegNum<[2]>; + def R3 : Ri< 3, "r3">, DwarfRegNum<[3]>; + def R4 : Ri< 4, "r4">, DwarfRegNum<[4]>; + def R5 : Ri< 5, "r5">, DwarfRegNum<[5]>; + def R6 : Ri< 6, "r6">, DwarfRegNum<[6]>; + def R7 : Ri< 7, "r7">, DwarfRegNum<[7]>; + def R8 : Ri< 8, "r8">, DwarfRegNum<[8]>; + def R9 : Ri< 9, "r9">, DwarfRegNum<[9]>; + def R10 : Ri<10, "r10">, DwarfRegNum<[10]>; + def R11 : Ri<11, "r11">, DwarfRegNum<[11]>; + def R12 : Ri<12, "r12">, DwarfRegNum<[12]>; + def R13 : Ri<13, "r13">, DwarfRegNum<[13]>; + def R14 : Ri<14, "r14">, DwarfRegNum<[14]>; + def R15 : Ri<15, "r15">, DwarfRegNum<[15]>; + def R16 : Ri<16, "r16">, DwarfRegNum<[16]>; + def R17 : Ri<17, "r17">, DwarfRegNum<[17]>; + def R18 : Ri<18, "r18">, DwarfRegNum<[18]>; + def R19 : Ri<19, "r19">, DwarfRegNum<[19]>; + def R20 : Ri<20, "r20">, DwarfRegNum<[20]>; + def R21 : Ri<21, "r21">, DwarfRegNum<[21]>; + def R22 : Ri<22, "r22">, DwarfRegNum<[22]>; + def R23 : Ri<23, "r23">, DwarfRegNum<[23]>; + def R24 : Ri<24, "r24">, DwarfRegNum<[24]>; + def R25 : Ri<25, "r25">, DwarfRegNum<[25]>; + def R26 : Ri<26, "r26">, DwarfRegNum<[26]>; + def R27 : Ri<27, "r27">, DwarfRegNum<[27]>; + def R28 : Ri<28, "r28">, DwarfRegNum<[28]>; + def R29 : Ri<29, "r29">, DwarfRegNum<[29]>; + def R30 : Ri<30, "r30">, DwarfRegNum<[30]>; + def R31 : Ri<31, "r31">, DwarfRegNum<[31]>; + + + def PC : Ri<31, "r31">, DwarfRegNum<[32]>; + def GP : Ri<31, "r31">, DwarfRegNum<[33]>; + + // Aliases of the R* registers used to hold 64-bit int values (doubles). + let SubRegIndices = [subreg_loreg, subreg_hireg] in { + def D0 : Rd< 0, "r1:0", [R0, R1]>, DwarfRegNum<[32]>; + def D1 : Rd< 2, "r3:2", [R2, R3]>, DwarfRegNum<[34]>; + def D2 : Rd< 4, "r5:4", [R4, R5]>, DwarfRegNum<[36]>; + def D3 : Rd< 6, "r7:6", [R6, R7]>, DwarfRegNum<[38]>; + def D4 : Rd< 8, "r9:8", [R8, R9]>, DwarfRegNum<[40]>; + def D5 : Rd<10, "r11:10", [R10, R11]>, DwarfRegNum<[42]>; + def D6 : Rd<12, "r13:12", [R12, R13]>, DwarfRegNum<[44]>; + def D7 : Rd<14, "r15:14", [R14, R15]>, DwarfRegNum<[46]>; + def D8 : Rd<16, "r17:16", [R16, R17]>, DwarfRegNum<[48]>; + def D9 : Rd<18, "r19:18", [R18, R19]>, DwarfRegNum<[50]>; + def D10 : Rd<20, "r21:20", [R20, R21]>, DwarfRegNum<[52]>; + def D11 : Rd<22, "r23:22", [R22, R23]>, DwarfRegNum<[54]>; + def D12 : Rd<24, "r25:24", [R24, R25]>, DwarfRegNum<[56]>; + def D13 : Rd<26, "r27:26", [R26, R27]>, DwarfRegNum<[58]>; + def D14 : Rd<28, "r29:28", [R28, R29]>, DwarfRegNum<[60]>; + def D15 : Rd<30, "r31:30", [R30, R31]>, DwarfRegNum<[62]>; + } + + // Predicate registers. + def P0 : Rp< 0, "p0">, DwarfRegNum<[63]>; + def P1 : Rp< 0, "p1">, DwarfRegNum<[64]>; + def P2 : Rp< 0, "p2">, DwarfRegNum<[65]>; + def P3 : Rp< 0, "p3">, DwarfRegNum<[66]>; + + // Control registers. + def SA0 : Rc<0, "sa0">, DwarfRegNum<[67]>; + def LC0 : Rc<0, "lc0">, DwarfRegNum<[68]>; + + def SA1 : Rc<0, "sa1">, DwarfRegNum<[69]>; + def LC1 : Rc<0, "lc1">, DwarfRegNum<[70]>; +} + + + + + + + + + + +// Register classes. +// +// FIXME: the register order should be defined in terms of the preferred +// allocation order... +// +def IntRegs : RegisterClass<"Hexagon", [i32], 32, (add (sequence "R%u", 0, 9), + (sequence "R%u", 12, 28), + R10, R11, R29, R30, + R31)> { +} + + + +def DoubleRegs : RegisterClass<"Hexagon", [i64], 64, (add (sequence "D%u", 0, + 4), + (sequence "D%u", 6, 13), + D5, D14, D15)> { + let SubRegClasses = [(IntRegs subreg_loreg, subreg_hireg)]; +} + + +def PredRegs : RegisterClass<"Hexagon", [i1], 32, (add (sequence "P%u", 0, 3))> +{ + let Size = 32; +} + +def CRRegs : RegisterClass<"Hexagon", [i32], 32, (add (sequence "LC%u", 0, 1), + (sequence "SA%u", 0, 1), + PC)> { + let Size = 32; +} diff --git a/lib/Target/Hexagon/HexagonRemoveSZExtArgs.cpp b/lib/Target/Hexagon/HexagonRemoveSZExtArgs.cpp new file mode 100644 index 0000000000..3ca257fc62 --- /dev/null +++ b/lib/Target/Hexagon/HexagonRemoveSZExtArgs.cpp @@ -0,0 +1,85 @@ +//=- HexagonRemoveExtendArgs.cpp - Remove unecessary argument sign extends --=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Pass that removes sign extends for function parameters. These parameters +// are already sign extended by the caller per Hexagon's ABI +// +//===----------------------------------------------------------------------===// + + + +#include "llvm/Pass.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/CodeGen/MachineFunctionAnalysis.h" +#include "HexagonTargetMachine.h" +#include <iostream> + +using namespace llvm; +namespace { + struct HexagonRemoveExtendArgs : public FunctionPass { + public: + static char ID; + HexagonRemoveExtendArgs() : FunctionPass(ID) {} + virtual bool runOnFunction(Function &F); + + const char *getPassName() const { + return "Remove sign extends"; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired<MachineFunctionAnalysis>(); + AU.addPreserved<MachineFunctionAnalysis>(); + FunctionPass::getAnalysisUsage(AU); + } + }; +} + +char HexagonRemoveExtendArgs::ID = 0; +RegisterPass<HexagonRemoveExtendArgs> X("reargs", + "Remove Sign and Zero Extends for Args" + ); + + + +bool HexagonRemoveExtendArgs::runOnFunction(Function &F) { + unsigned Idx = 1; + for (Function::arg_iterator AI = F.arg_begin(), AE = F.arg_end(); AI != AE; + ++AI, ++Idx) { + if (F.paramHasAttr(Idx, Attribute::SExt)) { + Argument* Arg = AI; + if (!isa<PointerType>(Arg->getType())) { + for (Instruction::use_iterator UI = Arg->use_begin(); + UI != Arg->use_end();) { + if (isa<SExtInst>(*UI)) { + Instruction* Use = cast<Instruction>(*UI); + SExtInst* SI = new SExtInst(Arg, Use->getType()); + assert (EVT::getEVT(SI->getType()) == + (EVT::getEVT(Use->getType()))); + ++UI; + Use->replaceAllUsesWith(SI); + Instruction* First = F.getEntryBlock().begin(); + SI->insertBefore(First); + Use->eraseFromParent(); + } else { + ++UI; + } + } + } + } + } + return true; +} + + + +FunctionPass *llvm::createHexagonRemoveExtendOps(HexagonTargetMachine &TM) { + return new HexagonRemoveExtendArgs(); +} diff --git a/lib/Target/Hexagon/HexagonSchedule.td b/lib/Target/Hexagon/HexagonSchedule.td new file mode 100644 index 0000000000..427d1cb138 --- /dev/null +++ b/lib/Target/Hexagon/HexagonSchedule.td @@ -0,0 +1,53 @@ +//===-HexagonSchedule.td - Hexagon Scheduling Definitions -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Functional Units +def LUNIT : FuncUnit; +def LSUNIT : FuncUnit; +def MUNIT : FuncUnit; +def SUNIT : FuncUnit; + + +// Itinerary classes +def ALU32 : InstrItinClass; +def ALU64 : InstrItinClass; +def CR : InstrItinClass; +def J : InstrItinClass; +def JR : InstrItinClass; +def LD : InstrItinClass; +def M : InstrItinClass; +def ST : InstrItinClass; +def S : InstrItinClass; +def PSEUDO : InstrItinClass; + + +def HexagonItineraries : + ProcessorItineraries<[LUNIT, LSUNIT, MUNIT, SUNIT], [], [ + InstrItinData<ALU32 , [InstrStage<1, [LUNIT, LSUNIT, MUNIT, SUNIT]>]>, + InstrItinData<ALU64 , [InstrStage<1, [MUNIT, SUNIT]>]>, + InstrItinData<CR , [InstrStage<1, [SUNIT]>]>, + InstrItinData<J , [InstrStage<1, [SUNIT, MUNIT]>]>, + InstrItinData<JR , [InstrStage<1, [MUNIT]>]>, + InstrItinData<LD , [InstrStage<1, [LUNIT, LSUNIT]>]>, + InstrItinData<M , [InstrStage<1, [MUNIT, SUNIT]>]>, + InstrItinData<ST , [InstrStage<1, [LSUNIT]>]>, + InstrItinData<S , [InstrStage<1, [SUNIT, MUNIT]>]>, + InstrItinData<PSEUDO , [InstrStage<1, [LUNIT, LSUNIT, MUNIT, SUNIT]>]> +]>; + + +//===----------------------------------------------------------------------===// +// V4 Machine Info + +//===----------------------------------------------------------------------===// + +include "HexagonScheduleV4.td" + +//===----------------------------------------------------------------------===// +// V4 Machine Info - +//===----------------------------------------------------------------------===// diff --git a/lib/Target/Hexagon/HexagonScheduleV4.td b/lib/Target/Hexagon/HexagonScheduleV4.td new file mode 100644 index 0000000000..4cf66fe743 --- /dev/null +++ b/lib/Target/Hexagon/HexagonScheduleV4.td @@ -0,0 +1,56 @@ +//=-HexagonScheduleV4.td - HexagonV4 Scheduling Definitions --*- tablegen -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// There are four SLOTS (four parallel pipelines) in Hexagon V4 machine. +// This file describes that machine information. + +// +// |===========|==================================================| +// | PIPELINE | Instruction Classes | +// |===========|==================================================| +// | SLOT0 | LD ST ALU32 MEMOP NV SYSTEM | +// |-----------|--------------------------------------------------| +// | SLOT1 | LD ST ALU32 | +// |-----------|--------------------------------------------------| +// | SLOT2 | XTYPE ALU32 J JR | +// |-----------|--------------------------------------------------| +// | SLOT3 | XTYPE ALU32 J CR | +// |===========|==================================================| + + +// Functional Units. +def SLOT0 : FuncUnit; +def SLOT1 : FuncUnit; +def SLOT2 : FuncUnit; +def SLOT3 : FuncUnit; + +// Itinerary classes. +def NV_V4 : InstrItinClass; +def MEM_V4 : InstrItinClass; +// ALU64/M/S Instruction classes of V2 are collectively knownn as XTYPE in V4. + +def HexagonItinerariesV4 : ProcessorItineraries< + [SLOT0, SLOT1, SLOT2, SLOT3], [], [ + InstrItinData<LD , [InstrStage<1, [SLOT0, SLOT1]>]>, + InstrItinData<ST , [InstrStage<1, [SLOT0, SLOT1]>]>, + InstrItinData<ALU32 , [InstrStage<1, [SLOT0, SLOT1, SLOT2, SLOT3]>]>, + InstrItinData<NV_V4 , [InstrStage<1, [SLOT0]>]>, + InstrItinData<MEM_V4 , [InstrStage<1, [SLOT0]>]>, + InstrItinData<J , [InstrStage<1, [SLOT2, SLOT3]>]>, + InstrItinData<JR , [InstrStage<1, [SLOT2]>]>, + InstrItinData<CR , [InstrStage<1, [SLOT3]>]>, + InstrItinData<PSEUDO , [InstrStage<1, [SLOT0, SLOT1, SLOT2, SLOT3]>]>, + InstrItinData<ALU64 , [InstrStage<1, [SLOT2, SLOT3]>]>, + InstrItinData<M , [InstrStage<1, [SLOT2, SLOT3]>]>, + InstrItinData<S , [InstrStage<1, [SLOT2, SLOT3]>]> +]>; + +//===----------------------------------------------------------------------===// +// Hexagon V4 Resource Definitions - +//===----------------------------------------------------------------------===// diff --git a/lib/Target/Hexagon/HexagonSelectCCInfo.td b/lib/Target/Hexagon/HexagonSelectCCInfo.td new file mode 100644 index 0000000000..f21d928c77 --- /dev/null +++ b/lib/Target/Hexagon/HexagonSelectCCInfo.td @@ -0,0 +1,121 @@ +//=-HexagoSelectCCInfo.td - Selectcc mappings ----------------*- tablegen -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +// +// selectcc mappings. +// +def : Pat <(i32 (selectcc IntRegs:$lhs, IntRegs:$rhs, IntRegs:$tval, + IntRegs:$fval, SETEQ)), + (i32 (MUX_rr (i1 (CMPEQrr IntRegs:$lhs, IntRegs:$rhs)), + IntRegs:$tval, IntRegs:$fval))>; + +def : Pat <(i32 (selectcc IntRegs:$lhs, IntRegs:$rhs, IntRegs:$tval, + IntRegs:$fval, SETNE)), + (i32 (MUX_rr (i1 (NOT_Ps (CMPEQrr IntRegs:$lhs, IntRegs:$rhs))), + IntRegs:$tval, IntRegs:$fval))>; + +def : Pat <(i32 (selectcc IntRegs:$lhs, IntRegs:$rhs, IntRegs:$tval, + IntRegs:$fval, SETGT)), + (i32 (MUX_rr (i1 (CMPGTrr IntRegs:$lhs, IntRegs:$rhs)), + IntRegs:$tval, IntRegs:$fval))>; + +def : Pat <(i32 (selectcc IntRegs:$lhs, IntRegs:$rhs, IntRegs:$tval, + IntRegs:$fval, SETUGT)), + (i32 (MUX_rr (i1 (CMPGTUrr IntRegs:$lhs, IntRegs:$rhs)), + IntRegs:$tval, IntRegs:$fval))>; + + + +def : Pat <(i32 (selectcc IntRegs:$lhs, IntRegs:$rhs, IntRegs:$tval, + IntRegs:$fval, SETULT)), + (i32 (MUX_rr (i1 (NOT_Ps (CMPGTUrr IntRegs:$lhs, + (ADD_ri IntRegs:$rhs, -1)))), + IntRegs:$tval, IntRegs:$fval))>; + +def : Pat <(i32 (selectcc IntRegs:$lhs, IntRegs:$rhs, IntRegs:$tval, + IntRegs:$fval, SETLT)), + (i32 (MUX_rr (i1 (NOT_Ps (CMPGTrr IntRegs:$lhs, + (ADD_ri IntRegs:$rhs, -1)))), + IntRegs:$tval, IntRegs:$fval))>; + +def : Pat <(i32 (selectcc IntRegs:$lhs, IntRegs:$rhs, IntRegs:$tval, + IntRegs:$fval, SETLE)), + (i32 (MUX_rr (i1 (NOT_Ps (CMPGTrr IntRegs:$lhs, IntRegs:$rhs))), + IntRegs:$tval, IntRegs:$fval))>; + +def : Pat <(i32 (selectcc IntRegs:$lhs, IntRegs:$rhs, IntRegs:$tval, + IntRegs:$fval, SETULE)), + (i32 (MUX_rr (i1 (NOT_Ps (CMPGTUrr IntRegs:$lhs, IntRegs:$rhs))), + IntRegs:$tval, IntRegs:$fval))>; + + +// +// selectcc mappings for greater-equal-to Rs => greater-than Rs-1. +// +def : Pat <(i32 (selectcc IntRegs:$lhs, IntRegs:$rhs, IntRegs:$tval, + IntRegs:$fval, SETGE)), + (i32 (MUX_rr (i1 (CMPGTrr IntRegs:$lhs, (ADD_ri IntRegs:$rhs, -1))), + IntRegs:$tval, IntRegs:$fval))>; + +def : Pat <(i32 (selectcc IntRegs:$lhs, IntRegs:$rhs, IntRegs:$tval, + IntRegs:$fval, SETUGE)), + (i32 (MUX_rr (i1 (CMPGTUrr IntRegs:$lhs, (ADD_ri IntRegs:$rhs, -1))), + IntRegs:$tval, IntRegs:$fval))>; + + + +// +// selectcc mappings for predicate comparisons. +// +// Convert Rd = selectcc(p0, p1, true_val, false_val, SETEQ) into: +// pt = not(p1 xor p2) +// Rd = mux(pt, true_val, false_val) +// and similarly for SETNE +// +def : Pat <(i32 (selectcc PredRegs:$lhs, PredRegs:$rhs, IntRegs:$tval, + IntRegs:$fval, SETNE)), + (i32 (MUX_rr (i1 (XOR_pp PredRegs:$lhs, PredRegs:$rhs)), IntRegs:$tval, + IntRegs:$fval))>; + +def : Pat <(i32 (selectcc PredRegs:$lhs, PredRegs:$rhs, IntRegs:$tval, + IntRegs:$fval, SETEQ)), + (i32 (MUX_rr (i1 (NOT_pp (XOR_pp PredRegs:$lhs, PredRegs:$rhs))), + IntRegs:$tval, IntRegs:$fval))>; + + +// +// selectcc mappings for 64-bit operands are messy. Hexagon does not have a +// MUX64 o, use this: +// selectcc(Rss, Rdd, tval, fval, cond) -> +// combine(mux(cmp_cond(Rss, Rdd), tval.hi, fval.hi), +// mux(cmp_cond(Rss, Rdd), tval.lo, fval.lo)) + +// setgt-64. +def : Pat<(i64 (selectcc DoubleRegs:$lhs, DoubleRegs:$rhs, DoubleRegs:$tval, + DoubleRegs:$fval, SETGT)), + (COMBINE_rr (MUX_rr (CMPGT64rr DoubleRegs:$lhs, DoubleRegs:$rhs), + (EXTRACT_SUBREG DoubleRegs:$tval, subreg_hireg), + (EXTRACT_SUBREG DoubleRegs:$fval, subreg_hireg)), + (MUX_rr (CMPGT64rr DoubleRegs:$lhs, DoubleRegs:$rhs), + (EXTRACT_SUBREG DoubleRegs:$tval, subreg_loreg), + (EXTRACT_SUBREG DoubleRegs:$fval, subreg_loreg)))>; + + +// setlt-64 -> setgt-64. +def : Pat<(i64 (selectcc DoubleRegs:$lhs, DoubleRegs:$rhs, DoubleRegs:$tval, + DoubleRegs:$fval, SETLT)), + (COMBINE_rr (MUX_rr (CMPGT64rr DoubleRegs:$lhs, + (ADD64_rr DoubleRegs:$rhs, (TFRI64 -1))), + (EXTRACT_SUBREG DoubleRegs:$tval, subreg_hireg), + (EXTRACT_SUBREG DoubleRegs:$fval, subreg_hireg)), + (MUX_rr (CMPGT64rr DoubleRegs:$lhs, + (ADD64_rr DoubleRegs:$rhs, (TFRI64 -1))), + (EXTRACT_SUBREG DoubleRegs:$tval, subreg_loreg), + (EXTRACT_SUBREG DoubleRegs:$fval, subreg_loreg)))>; diff --git a/lib/Target/Hexagon/HexagonSelectionDAGInfo.cpp b/lib/Target/Hexagon/HexagonSelectionDAGInfo.cpp new file mode 100644 index 0000000000..a52c604505 --- /dev/null +++ b/lib/Target/Hexagon/HexagonSelectionDAGInfo.cpp @@ -0,0 +1,46 @@ +//===-- HexagonSelectionDAGInfo.cpp - Hexagon SelectionDAG Info -----------===// +// +// 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 HexagonSelectionDAGInfo class. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "hexagon-selectiondag-info" +#include "HexagonTargetMachine.h" +using namespace llvm; + +bool llvm::flag_aligned_memcpy; + +HexagonSelectionDAGInfo::HexagonSelectionDAGInfo(const HexagonTargetMachine + &TM) + : TargetSelectionDAGInfo(TM) { +} + +HexagonSelectionDAGInfo::~HexagonSelectionDAGInfo() { +} + +SDValue +HexagonSelectionDAGInfo:: +EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl, SDValue Chain, + SDValue Dst, SDValue Src, SDValue Size, unsigned Align, + bool isVolatile, bool AlwaysInline, + MachinePointerInfo DstPtrInfo, + MachinePointerInfo SrcPtrInfo) const { + flag_aligned_memcpy = false; + if ((Align & 0x3) == 0) { + ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size); + if (ConstantSize) { + uint64_t SizeVal = ConstantSize->getZExtValue(); + if ((SizeVal > 32) && ((SizeVal % 8) == 0)) + flag_aligned_memcpy = true; + } + } + + return SDValue(); +} diff --git a/lib/Target/Hexagon/HexagonSelectionDAGInfo.h b/lib/Target/Hexagon/HexagonSelectionDAGInfo.h new file mode 100644 index 0000000000..86fa026f3f --- /dev/null +++ b/lib/Target/Hexagon/HexagonSelectionDAGInfo.h @@ -0,0 +1,40 @@ +//=-- HexagonSelectionDAGInfo.h - Hexagon SelectionDAG Info ------*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the Hexagon subclass for TargetSelectionDAGInfo. +// +//===----------------------------------------------------------------------===// + +#ifndef HexagonSELECTIONDAGINFO_H +#define HexagonSELECTIONDAGINFO_H + +#include "llvm/Target/TargetSelectionDAGInfo.h" + +namespace llvm { + +class HexagonTargetMachine; + +class HexagonSelectionDAGInfo : public TargetSelectionDAGInfo { +public: + explicit HexagonSelectionDAGInfo(const HexagonTargetMachine &TM); + ~HexagonSelectionDAGInfo(); + + virtual + SDValue EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl, + SDValue Chain, + SDValue Dst, SDValue Src, + SDValue Size, unsigned Align, + bool isVolatile, bool AlwaysInline, + MachinePointerInfo DstPtrInfo, + MachinePointerInfo SrcPtrInfo) const; +}; + +} + +#endif diff --git a/lib/Target/Hexagon/HexagonSplitTFRCondSets.cpp b/lib/Target/Hexagon/HexagonSplitTFRCondSets.cpp new file mode 100644 index 0000000000..f4d3647dea --- /dev/null +++ b/lib/Target/Hexagon/HexagonSplitTFRCondSets.cpp @@ -0,0 +1,136 @@ +//===---- HexagonSplitTFRCondSets.cpp - split TFR condsets into xfers -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// +//===----------------------------------------------------------------------===//// +// This pass tries to provide opportunities for better optimization of muxes. +// The default code generated for something like: flag = (a == b) ? 1 : 3; +// would be: +// +// {p0 = cmp.eq(r0,r1)} +// {r3 = mux(p0,#1,#3)} +// +// This requires two packets. If we use .new predicated immediate transfers, +// then we can do this in a single packet, e.g.: +// +// {p0 = cmp.eq(r0,r1) +// if (p0.new) r3 = #1 +// if (!p0.new) r3 = #3} +// +// Note that the conditional assignments are not generated in .new form here. +// We assume opptimisically that they will be formed later. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "xfer" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/LatencyPriorityQueue.h" +#include "llvm/CodeGen/SchedulerRegistry.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/ScheduleHazardRecognizer.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "HexagonTargetMachine.h" +#include "HexagonSubtarget.h" +#include "HexagonMachineFunctionInfo.h" +#include <map> +#include <iostream> + +#include "llvm/Support/CommandLine.h" +#define DEBUG_TYPE "xfer" + + +using namespace llvm; + +namespace { + +class HexagonSplitTFRCondSets : public MachineFunctionPass { + HexagonTargetMachine& QTM; + const HexagonSubtarget &QST; + + public: + static char ID; + HexagonSplitTFRCondSets(HexagonTargetMachine& TM) : + MachineFunctionPass(ID), QTM(TM), QST(*TM.getSubtargetImpl()) {} + + const char *getPassName() const { + return "Hexagon Split TFRCondSets"; + } + bool runOnMachineFunction(MachineFunction &Fn); +}; + + +char HexagonSplitTFRCondSets::ID = 0; + + +bool HexagonSplitTFRCondSets::runOnMachineFunction(MachineFunction &Fn) { + + const TargetInstrInfo *TII = QTM.getInstrInfo(); + + // Loop over all of the basic blocks. + for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end(); + MBBb != MBBe; ++MBBb) { + MachineBasicBlock* MBB = MBBb; + // Traverse the basic block. + for (MachineBasicBlock::iterator MII = MBB->begin(); MII != MBB->end(); + ++MII) { + MachineInstr *MI = MII; + int Opc = MI->getOpcode(); + if (Opc == Hexagon::TFR_condset_rr) { + + int DestReg = MI->getOperand(0).getReg(); + int SrcReg1 = MI->getOperand(2).getReg(); + int SrcReg2 = MI->getOperand(3).getReg(); + + // Minor optimization: do not emit the predicated copy if the source and + // the destination is the same register + if (DestReg != SrcReg1) { + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_cPt), + DestReg).addReg(MI->getOperand(1).getReg()).addReg(SrcReg1); + } + if (DestReg != SrcReg2) { + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_cNotPt), + DestReg).addReg(MI->getOperand(1).getReg()).addReg(SrcReg2); + } + MII = MBB->erase(MI); + --MII; + } else if (Opc == Hexagon::TFR_condset_ii) { + int DestReg = MI->getOperand(0).getReg(); + int SrcReg1 = MI->getOperand(1).getReg(); + int Immed1 = MI->getOperand(2).getImm(); + int Immed2 = MI->getOperand(3).getImm(); + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFRI_cPt), + DestReg).addReg(SrcReg1).addImm(Immed1); + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFRI_cNotPt), + DestReg).addReg(SrcReg1).addImm(Immed2); + MII = MBB->erase(MI); + --MII; + } + } + } + + return true; +} + +} + +//===----------------------------------------------------------------------===// +// Public Constructor Functions +//===----------------------------------------------------------------------===// + +FunctionPass *llvm::createHexagonSplitTFRCondSets(HexagonTargetMachine &TM) { + return new HexagonSplitTFRCondSets(TM); +} diff --git a/lib/Target/Hexagon/HexagonSubtarget.cpp b/lib/Target/Hexagon/HexagonSubtarget.cpp new file mode 100644 index 0000000000..c0aa21b976 --- /dev/null +++ b/lib/Target/Hexagon/HexagonSubtarget.cpp @@ -0,0 +1,60 @@ +//===- HexagonSubtarget.cpp - Hexagon Subtarget Information ---------------===// +// +// 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 Hexagon specific subclass of TargetSubtarget. +// +//===----------------------------------------------------------------------===// + +#include "HexagonSubtarget.h" +#include "Hexagon.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" +using namespace llvm; + +#define GET_SUBTARGETINFO_MC_DESC +#define GET_SUBTARGETINFO_CTOR +#define GET_SUBTARGETINFO_TARGET_DESC +#include "HexagonGenSubtargetInfo.inc" + +static cl::opt<bool> +EnableV3("enable-hexagon-v3", cl::Hidden, + cl::desc("Enable Hexagon V3 instructions.")); + +static cl::opt<bool> +EnableMemOps( + "enable-hexagon-memops", + cl::Hidden, cl::ZeroOrMore, cl::ValueDisallowed, + cl::desc("Generate V4 MEMOP in code generation for Hexagon target")); + +HexagonSubtarget::HexagonSubtarget(StringRef TT, StringRef CPU, StringRef FS): + HexagonGenSubtargetInfo(TT, CPU, FS), + HexagonArchVersion(V1), + CPUString(CPU.str()) { + ParseSubtargetFeatures(CPU, FS); + + switch(HexagonArchVersion) { + case HexagonSubtarget::V2: + break; + case HexagonSubtarget::V3: + EnableV3 = true; + break; + case HexagonSubtarget::V4: + break; + default: + llvm_unreachable("Unknown Architecture Version."); + } + + // Initialize scheduling itinerary for the specified CPU. + InstrItins = getInstrItineraryForCPU(CPUString); + + if (EnableMemOps) + UseMemOps = true; + else + UseMemOps = false; +} diff --git a/lib/Target/Hexagon/HexagonSubtarget.h b/lib/Target/Hexagon/HexagonSubtarget.h new file mode 100644 index 0000000000..6de85df7f0 --- /dev/null +++ b/lib/Target/Hexagon/HexagonSubtarget.h @@ -0,0 +1,74 @@ +//==-- HexagonSubtarget.h - Define Subtarget for the Hexagon ----*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the Hexagon specific subclass of TargetSubtarget. +// +//===----------------------------------------------------------------------===// + +#ifndef Hexagon_SUBTARGET_H +#define Hexagon_SUBTARGET_H + +#include "llvm/Target/TargetSubtargetInfo.h" +#include "llvm/Target/TargetMachine.h" +#include <string> + +#define GET_SUBTARGETINFO_HEADER +#include "HexagonGenSubtargetInfo.inc" + +#define Hexagon_SMALL_DATA_THRESHOLD 8 + +namespace llvm { + +class HexagonSubtarget : public HexagonGenSubtargetInfo { + + bool UseMemOps; + +public: + enum HexagonArchEnum { + V1, V2, V3, V4 + }; + + HexagonArchEnum HexagonArchVersion; + std::string CPUString; + InstrItineraryData InstrItins; + +public: + HexagonSubtarget(StringRef TT, StringRef CPU, StringRef FS); + + /// getInstrItins - Return the instruction itineraies based on subtarget + /// selection. + const InstrItineraryData &getInstrItineraryData() const { return InstrItins; } + + + /// ParseSubtargetFeatures - Parses features string setting specified + /// subtarget options. Definition of function is auto generated by tblgen. + void ParseSubtargetFeatures(StringRef CPU, StringRef FS); + + bool hasV2TOps () const { return HexagonArchVersion >= V2; } + bool hasV2TOpsOnly () const { return HexagonArchVersion == V2; } + bool hasV3TOps () const { return HexagonArchVersion >= V3; } + bool hasV3TOpsOnly () const { return HexagonArchVersion == V3; } + bool hasV4TOps () const { return HexagonArchVersion >= V4; } + bool useMemOps () const { return HexagonArchVersion >= V4 && UseMemOps; } + + bool isSubtargetV2() const { return HexagonArchVersion == V2;} + const std::string &getCPUString () const { return CPUString; } + + // Threshold for small data section + unsigned getSmallDataThreshold() const { + return Hexagon_SMALL_DATA_THRESHOLD; + } + const HexagonArchEnum &getHexagonArchVersion() const { + return HexagonArchVersion; + } +}; + +} // end namespace llvm + +#endif diff --git a/lib/Target/Hexagon/HexagonTargetMachine.cpp b/lib/Target/Hexagon/HexagonTargetMachine.cpp new file mode 100644 index 0000000000..09b7dd51a6 --- /dev/null +++ b/lib/Target/Hexagon/HexagonTargetMachine.cpp @@ -0,0 +1,128 @@ +//===-- HexagonTargetMachine.cpp - Define TargetMachine for Hexagon -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +#include "HexagonMCAsmInfo.h" +#include "HexagonTargetMachine.h" +#include "Hexagon.h" +#include "HexagonISelLowering.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/PassManager.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Transforms/IPO/PassManagerBuilder.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Support/TargetRegistry.h" +#include <iostream> + +#define GET_REGINFO_MC_DESC +#define GET_REGINFO_TARGET_DESC +#include "HexagonGenRegisterInfo.inc" + +extern "C" void LLVMInitializeHexagonTargetMC() {} + +using namespace llvm; + +static cl:: +opt<bool> DisableHardwareLoops( + "disable-hexagon-hwloops", cl::Hidden, + cl::desc("Disable Hardware Loops for Hexagon target")); + +/// HexagonTargetMachineModule - Note that this is used on hosts that +/// cannot link in a library unless there are references into the +/// library. In particular, it seems that it is not possible to get +/// things to work on Win32 without this. Though it is unused, do not +/// remove it. +extern "C" int HexagonTargetMachineModule; +int HexagonTargetMachineModule = 0; + +extern "C" void LLVMInitializeHexagonTarget() { + // Register the target. + RegisterTargetMachine<HexagonTargetMachine> X(TheHexagonTarget); + + // Register the target asm info. + RegisterMCAsmInfo<HexagonMCAsmInfo> A(TheHexagonTarget); +} + + +/// HexagonTargetMachine ctor - Create an ILP32 architecture model. +/// + +/// Hexagon_TODO: Do I need an aggregate alignment? +/// +HexagonTargetMachine::HexagonTargetMachine(const Target &T, StringRef TT, + StringRef CPU, StringRef FS, + TargetOptions Options, + Reloc::Model RM, + CodeModel::Model CM, + CodeGenOpt::Level OL) + : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL), + DataLayout("e-p:32:32:32-i64:64:64-i32:32:32-i16:16:16-i1:32:32-a0:0") , + Subtarget(TT, CPU, FS), TLInfo(*this), InstrInfo(Subtarget), + TSInfo(*this), + FrameLowering(Subtarget), + InstrItins(&Subtarget.getInstrItineraryData()) { + setMCUseCFI(false); +} + +// addPassesForOptimizations - Allow the backend (target) to add Target +// Independent Optimization passes to the Pass Manager. +bool HexagonTargetMachine::addPassesForOptimizations(PassManagerBase &PM) { + + PM.add(createConstantPropagationPass()); + PM.add(createLoopSimplifyPass()); + PM.add(createDeadCodeEliminationPass()); + PM.add(createConstantPropagationPass()); + PM.add(createLoopUnrollPass()); + PM.add(createLoopStrengthReducePass(getTargetLowering())); + return true; +} + +bool HexagonTargetMachine::addInstSelector(PassManagerBase &PM) { + PM.add(createHexagonRemoveExtendOps(*this)); + PM.add(createHexagonISelDag(*this)); + return false; +} + + +bool HexagonTargetMachine::addPreRegAlloc(PassManagerBase &PM) { + if (!DisableHardwareLoops) { + PM.add(createHexagonHardwareLoops()); + } + + return false; +} + +bool HexagonTargetMachine::addPostRegAlloc(PassManagerBase &PM) { + PM.add(createHexagonCFGOptimizer(*this)); + return true; +} + + +bool HexagonTargetMachine::addPreSched2(PassManagerBase &PM) { + PM.add(createIfConverterPass()); + return true; +} + +bool HexagonTargetMachine::addPreEmitPass(PassManagerBase &PM) { + + if (!DisableHardwareLoops) { + PM.add(createHexagonFixupHwLoops()); + } + + // Expand Spill code for predicate registers. + PM.add(createHexagonExpandPredSpillCode(*this)); + + // Split up TFRcondsets into conditional transfers. + PM.add(createHexagonSplitTFRCondSets(*this)); + + return false; +} diff --git a/lib/Target/Hexagon/HexagonTargetMachine.h b/lib/Target/Hexagon/HexagonTargetMachine.h new file mode 100644 index 0000000000..e27d3ae943 --- /dev/null +++ b/lib/Target/Hexagon/HexagonTargetMachine.h @@ -0,0 +1,86 @@ +//=-- HexagonTargetMachine.h - Define TargetMachine for Hexagon ---*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the Hexagon specific subclass of TargetMachine. +// +//===----------------------------------------------------------------------===// + +#ifndef HexagonTARGETMACHINE_H +#define HexagonTARGETMACHINE_H + +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetData.h" +#include "HexagonInstrInfo.h" +#include "HexagonSubtarget.h" +#include "HexagonISelLowering.h" +#include "HexagonSelectionDAGInfo.h" +#include "HexagonFrameLowering.h" + +namespace llvm { + +class Module; + +class HexagonTargetMachine : public LLVMTargetMachine { + const TargetData DataLayout; // Calculates type size & alignment. + HexagonSubtarget Subtarget; + HexagonTargetLowering TLInfo; + HexagonInstrInfo InstrInfo; + HexagonSelectionDAGInfo TSInfo; + HexagonFrameLowering FrameLowering; + const InstrItineraryData* InstrItins; + +public: + HexagonTargetMachine(const Target &T, StringRef TT,StringRef CPU, + StringRef FS, TargetOptions Options, Reloc::Model RM, + CodeModel::Model CM, CodeGenOpt::Level OL); + + virtual const HexagonInstrInfo *getInstrInfo() const { + return &InstrInfo; + } + virtual const HexagonSubtarget *getSubtargetImpl() const { + return &Subtarget; + } + virtual const HexagonRegisterInfo *getRegisterInfo() const { + return &InstrInfo.getRegisterInfo(); + } + + virtual const InstrItineraryData* getInstrItineraryData() const { + return InstrItins; + } + + + virtual const HexagonTargetLowering* getTargetLowering() const { + return &TLInfo; + } + + virtual const HexagonFrameLowering* getFrameLowering() const { + return &FrameLowering; + } + + virtual const HexagonSelectionDAGInfo* getSelectionDAGInfo() const { + return &TSInfo; + } + + virtual const TargetData *getTargetData() const { return &DataLayout; } + static unsigned getModuleMatchQuality(const Module &M); + + // Pass Pipeline Configuration. + virtual bool addPassesForOptimizations(PassManagerBase &PM); + virtual bool addInstSelector(PassManagerBase &PM); + virtual bool addPreEmitPass(PassManagerBase &PM); + virtual bool addPreRegAlloc(llvm::PassManagerBase &PM); + virtual bool addPostRegAlloc(PassManagerBase &PM); + virtual bool addPreSched2(PassManagerBase &PM); +}; + +extern bool flag_aligned_memcpy; + +} // end namespace llvm + +#endif diff --git a/lib/Target/Hexagon/HexagonTargetObjectFile.cpp b/lib/Target/Hexagon/HexagonTargetObjectFile.cpp new file mode 100644 index 0000000000..188337d470 --- /dev/null +++ b/lib/Target/Hexagon/HexagonTargetObjectFile.cpp @@ -0,0 +1,94 @@ +//===-- HexagonTargetObjectFile.cpp - Hexagon asm properties ----*- 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 the declarations of the HexagonTargetAsmInfo properties. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Target/TargetData.h" +#include "llvm/DerivedTypes.h" +#include "llvm/MC/MCContext.h" +#include "llvm/Support/ELF.h" +#include "llvm/Support/CommandLine.h" +#include "HexagonSubtarget.h" +#include "HexagonTargetObjectFile.h" +#include "HexagonTargetMachine.h" + +using namespace llvm; + +static cl::opt<int> SmallDataThreshold("hexagon-small-data-threshold", + cl::init(8), cl::Hidden); + +void HexagonTargetObjectFile::Initialize(MCContext &Ctx, + const TargetMachine &TM) { + TargetLoweringObjectFileELF::Initialize(Ctx, TM); + + + SmallDataSection = + getContext().getELFSection(".sdata", ELF::SHT_PROGBITS, + ELF::SHF_WRITE | ELF::SHF_ALLOC, + SectionKind::getDataRel()); + SmallBSSSection = + getContext().getELFSection(".sbss", ELF::SHT_NOBITS, + ELF::SHF_WRITE | ELF::SHF_ALLOC, + SectionKind::getBSS()); +} + +// sdata/sbss support taken largely from the MIPS Backend. +static bool IsInSmallSection(uint64_t Size) { + return Size > 0 && Size <= (uint64_t)SmallDataThreshold; +} +/// IsGlobalInSmallSection - Return true if this global value should be +/// placed into small data/bss section. +bool HexagonTargetObjectFile::IsGlobalInSmallSection(const GlobalValue *GV, + const TargetMachine &TM) const { + // If the primary definition of this global value is outside the current + // translation unit or the global value is available for inspection but not + // emission, then do nothing. + if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage()) + return false; + + // Otherwise, Check if GV should be in sdata/sbss, when normally it would end + // up in getKindForGlobal(GV, TM). + return IsGlobalInSmallSection(GV, TM, getKindForGlobal(GV, TM)); +} + +/// IsGlobalInSmallSection - Return true if this global value should be +/// placed into small data/bss section. +bool HexagonTargetObjectFile:: +IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM, + SectionKind Kind) const { + // Only global variables, not functions. + const GlobalVariable *GVA = dyn_cast<GlobalVariable>(GV); + if (!GVA) + return false; + + if (Kind.isBSS() || Kind.isDataNoRel() || Kind.isCommon()) { + Type *Ty = GV->getType()->getElementType(); + return IsInSmallSection(TM.getTargetData()->getTypeAllocSize(Ty)); + } + + return false; +} + +const MCSection *HexagonTargetObjectFile:: +SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const { + + // Handle Small Section classification here. + if (Kind.isBSS() && IsGlobalInSmallSection(GV, TM, Kind)) + return SmallBSSSection; + if (Kind.isDataNoRel() && IsGlobalInSmallSection(GV, TM, Kind)) + return SmallDataSection; + + // Otherwise, we work the same as ELF. + return TargetLoweringObjectFileELF::SelectSectionForGlobal(GV, Kind, Mang,TM); +} diff --git a/lib/Target/Hexagon/HexagonTargetObjectFile.h b/lib/Target/Hexagon/HexagonTargetObjectFile.h new file mode 100644 index 0000000000..101c1f2d3e --- /dev/null +++ b/lib/Target/Hexagon/HexagonTargetObjectFile.h @@ -0,0 +1,40 @@ +//===-- HexagonTargetAsmInfo.h - Hexagon asm properties ---------*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef HexagonTARGETOBJECTFILE_H +#define HexagonTARGETOBJECTFILE_H + +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include "llvm/MC/MCSectionELF.h" + +namespace llvm { + + class HexagonTargetObjectFile : public TargetLoweringObjectFileELF { + const MCSectionELF *SmallDataSection; + const MCSectionELF *SmallBSSSection; + public: + virtual void Initialize(MCContext &Ctx, const TargetMachine &TM); + + /// IsGlobalInSmallSection - Return true if this global address should be + /// placed into small data/bss section. + bool IsGlobalInSmallSection(const GlobalValue *GV, + const TargetMachine &TM, + SectionKind Kind) const; + bool IsGlobalInSmallSection(const GlobalValue *GV, + const TargetMachine &TM) const; + + const MCSection* SelectSectionForGlobal(const GlobalValue *GV, + SectionKind Kind, + Mangler *Mang, + const TargetMachine &TM) const; + }; + +} // namespace llvm + +#endif diff --git a/lib/Target/Hexagon/HexagonVarargsCallingConvention.h b/lib/Target/Hexagon/HexagonVarargsCallingConvention.h new file mode 100644 index 0000000000..21b2d678ac --- /dev/null +++ b/lib/Target/Hexagon/HexagonVarargsCallingConvention.h @@ -0,0 +1,141 @@ +//==-- HexagonVarargsCallingConvention.h - Calling Conventions ---*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the functions that assign locations to outgoing function +// arguments. Adapted from the target independent version but this handles +// calls to varargs functions +// +//===----------------------------------------------------------------------===// +// + + + + +static bool RetCC_Hexagon32_VarArgs(unsigned ValNo, EVT ValVT, + EVT LocVT, CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, + Hexagon_CCState &State, + int NonVarArgsParams, + int CurrentParam, + bool ForceMem); + + +static bool CC_Hexagon32_VarArgs(unsigned ValNo, EVT ValVT, + EVT LocVT, CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, + Hexagon_CCState &State, + int NonVarArgsParams, + int CurrentParam, + bool ForceMem) { + unsigned ByValSize = 0; + if (ArgFlags.isByVal() && + ((ByValSize = ArgFlags.getByValSize()) > + (MVT(MVT::i64).getSizeInBits() / 8))) { + ForceMem = true; + } + + + // Only assign registers for named (non varargs) arguments + if ( !ForceMem && ((NonVarArgsParams == -1) || (CurrentParam <= + NonVarArgsParams))) { + + if (LocVT == MVT::i32 || + LocVT == MVT::i16 || + LocVT == MVT::i8 || + LocVT == MVT::f32) { + static const unsigned RegList1[] = { + Hexagon::R0, Hexagon::R1, Hexagon::R2, Hexagon::R3, Hexagon::R4, + Hexagon::R5 + }; + if (unsigned Reg = State.AllocateReg(RegList1, 6)) { + State.addLoc(CCValAssign::getReg(ValNo, ValVT.getSimpleVT(), Reg, + LocVT.getSimpleVT(), LocInfo)); + return false; + } + } + + if (LocVT == MVT::i64 || + LocVT == MVT::f64) { + static const unsigned RegList2[] = { + Hexagon::D0, Hexagon::D1, Hexagon::D2 + }; + if (unsigned Reg = State.AllocateReg(RegList2, 3)) { + State.addLoc(CCValAssign::getReg(ValNo, ValVT.getSimpleVT(), Reg, + LocVT.getSimpleVT(), LocInfo)); + return false; + } + } + } + + const Type* ArgTy = LocVT.getTypeForEVT(State.getContext()); + unsigned Alignment = + State.getTarget().getTargetData()->getABITypeAlignment(ArgTy); + unsigned Size = + State.getTarget().getTargetData()->getTypeSizeInBits(ArgTy) / 8; + + // If it's passed by value, then we need the size of the aggregate not of + // the pointer. + if (ArgFlags.isByVal()) { + Size = ByValSize; + + // Hexagon_TODO: Get the alignment of the contained type here. + Alignment = 8; + } + + unsigned Offset3 = State.AllocateStack(Size, Alignment); + State.addLoc(CCValAssign::getMem(ValNo, ValVT.getSimpleVT(), Offset3, + LocVT.getSimpleVT(), LocInfo)); + return false; +} + + +static bool RetCC_Hexagon32_VarArgs(unsigned ValNo, EVT ValVT, + EVT LocVT, CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, + Hexagon_CCState &State, + int NonVarArgsParams, + int CurrentParam, + bool ForceMem) { + + if (LocVT == MVT::i32 || + LocVT == MVT::f32) { + static const unsigned RegList1[] = { + Hexagon::R0, Hexagon::R1, Hexagon::R2, Hexagon::R3, Hexagon::R4, + Hexagon::R5 + }; + if (unsigned Reg = State.AllocateReg(RegList1, 6)) { + State.addLoc(CCValAssign::getReg(ValNo, ValVT.getSimpleVT(), Reg, + LocVT.getSimpleVT(), LocInfo)); + return false; + } + } + + if (LocVT == MVT::i64 || + LocVT == MVT::f64) { + static const unsigned RegList2[] = { + Hexagon::D0, Hexagon::D1, Hexagon::D2 + }; + if (unsigned Reg = State.AllocateReg(RegList2, 3)) { + State.addLoc(CCValAssign::getReg(ValNo, ValVT.getSimpleVT(), Reg, + LocVT.getSimpleVT(), LocInfo)); + return false; + } + } + + const Type* ArgTy = LocVT.getTypeForEVT(State.getContext()); + unsigned Alignment = + State.getTarget().getTargetData()->getABITypeAlignment(ArgTy); + unsigned Size = + State.getTarget().getTargetData()->getTypeSizeInBits(ArgTy) / 8; + + unsigned Offset3 = State.AllocateStack(Size, Alignment); + State.addLoc(CCValAssign::getMem(ValNo, ValVT.getSimpleVT(), Offset3, + LocVT.getSimpleVT(), LocInfo)); + return false; +} diff --git a/lib/Target/Hexagon/LLVMBuild.txt b/lib/Target/Hexagon/LLVMBuild.txt new file mode 100644 index 0000000000..a9524dbfb4 --- /dev/null +++ b/lib/Target/Hexagon/LLVMBuild.txt @@ -0,0 +1,30 @@ +;===- ./lib/Target/Hexagon/LLVMBuild.txt ----------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = TargetGroup +name = Hexagon +parent = Target +has_asmprinter = 1 + +[component_1] +type = Library +name = HexagonCodeGen +parent = Hexagon +required_libraries = AsmPrinter CodeGen Core HexagonInfo SelectionDAG Support Target MC +add_to_library_groups = Hexagon + diff --git a/lib/Target/Hexagon/Makefile b/lib/Target/Hexagon/Makefile new file mode 100644 index 0000000000..836d303ef6 --- /dev/null +++ b/lib/Target/Hexagon/Makefile @@ -0,0 +1,23 @@ +##===- lib/Target/Hexagon/Makefile -------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../.. +LIBRARYNAME = LLVMHexagonCodeGen +TARGET = Hexagon + +# Make sure that tblgen is run, first thing. +BUILT_SOURCES = HexagonGenRegisterInfo.inc \ + HexagonGenInstrInfo.inc \ + HexagonGenAsmWriter.inc \ + HexagonGenDAGISel.inc HexagonGenSubtargetInfo.inc \ + HexagonGenCallingConv.inc \ + HexagonAsmPrinter.cpp + +DIRS = TargetInfo + +include $(LEVEL)/Makefile.common diff --git a/lib/Target/Hexagon/TargetInfo/CMakeLists.txt b/lib/Target/Hexagon/TargetInfo/CMakeLists.txt new file mode 100644 index 0000000000..960c8412c6 --- /dev/null +++ b/lib/Target/Hexagon/TargetInfo/CMakeLists.txt @@ -0,0 +1,14 @@ +include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. + ${CMAKE_CURRENT_SOURCE_DIR}/.. ) + +add_llvm_library(LLVMHexagonInfo + HexagonTargetInfo.cpp + ) + +add_llvm_library_dependencies(LLVMHexagonInfo + LLVMMC + LLVMSupport + LLVMTarget + ) + +add_dependencies(LLVMHexagonInfo HexagonCommonTableGen) diff --git a/lib/Target/Hexagon/TargetInfo/HexagonTargetInfo.cpp b/lib/Target/Hexagon/TargetInfo/HexagonTargetInfo.cpp new file mode 100644 index 0000000000..7aa5dd3b89 --- /dev/null +++ b/lib/Target/Hexagon/TargetInfo/HexagonTargetInfo.cpp @@ -0,0 +1,19 @@ +//===-- HexagonTargetInfo.cpp - Hexagon Target Implementation ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Hexagon.h" +#include "llvm/Module.h" +#include "llvm/Support/TargetRegistry.h" +using namespace llvm; + +Target llvm::TheHexagonTarget; + +extern "C" void LLVMInitializeHexagonTargetInfo() { + RegisterTarget<Triple::hexagon, /*HasJIT=*/false> X(TheHexagonTarget, "hexagon", "Hexagon"); +} diff --git a/lib/Target/Hexagon/TargetInfo/LLVMBuild.txt b/lib/Target/Hexagon/TargetInfo/LLVMBuild.txt new file mode 100644 index 0000000000..b5d0972f15 --- /dev/null +++ b/lib/Target/Hexagon/TargetInfo/LLVMBuild.txt @@ -0,0 +1,24 @@ +;===- ./lib/Target/Hexagon/TargetInfo/LLVMBuild.txt ------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Library +name = HexagonInfo +parent = Hexagon +required_libraries = MC Support +add_to_library_groups = Hexagon + diff --git a/lib/Target/Hexagon/TargetInfo/Makefile b/lib/Target/Hexagon/TargetInfo/Makefile new file mode 100644 index 0000000000..494cca1122 --- /dev/null +++ b/lib/Target/Hexagon/TargetInfo/Makefile @@ -0,0 +1,15 @@ +##===- lib/Target/Hexagon/TargetInfo/Makefile ----------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../../.. +LIBRARYNAME = LLVMHexagonInfo + +# Hack: we need to include 'main' target directory to grab private headers +CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/projects/sample/autoconf/configure.ac b/projects/sample/autoconf/configure.ac index ab15892127..a19e87ddf9 100644 --- a/projects/sample/autoconf/configure.ac +++ b/projects/sample/autoconf/configure.ac @@ -300,6 +300,7 @@ AC_CACHE_CHECK([target architecture],[llvm_cv_target_arch], mips-*) llvm_cv_target_arch="Mips" ;; xcore-*) llvm_cv_target_arch="XCore" ;; msp430-*) llvm_cv_target_arch="MSP430" ;; + hexagon-*) llvm_cv_target_arch="Hexagon" ;; mblaze-*) llvm_cv_target_arch="MBlaze" ;; ptx-*) llvm_cv_target_arch="PTX" ;; *) llvm_cv_target_arch="Unknown" ;; @@ -434,6 +435,7 @@ else Mips) AC_SUBST(TARGET_HAS_JIT,1) ;; XCore) AC_SUBST(TARGET_HAS_JIT,0) ;; MSP430) AC_SUBST(TARGET_HAS_JIT,0) ;; + Hexagon) AC_SUBST(TARGET_HAS_JIT,0) ;; MBlaze) AC_SUBST(TARGET_HAS_JIT,0) ;; PTX) AC_SUBST(TARGET_HAS_JIT,0) ;; *) AC_SUBST(TARGET_HAS_JIT,0) ;; @@ -545,14 +547,14 @@ dnl Allow specific targets to be specified for building (or not) TARGETS_TO_BUILD="" AC_ARG_ENABLE([targets],AS_HELP_STRING([--enable-targets], [Build specific host targets: all or target1,target2,... Valid targets are: - host, x86, x86_64, sparc, powerpc, arm, mips, spu, + host, x86, x86_64, sparc, powerpc, arm, mips, spu, hexagon, xcore, msp430, ptx, cbe, and cpp (default=all)]),, enableval=all) if test "$enableval" = host-only ; then enableval=host fi case "$enableval" in - all) TARGETS_TO_BUILD="X86 Sparc PowerPC ARM Mips CellSPU XCore MSP430 CBackend CppBackend MBlaze PTX" ;; + all) TARGETS_TO_BUILD="X86 Sparc PowerPC ARM Mips CellSPU XCore MSP430 Hexagon CBackend CppBackend MBlaze PTX" ;; *)for a_target in `echo $enableval|sed -e 's/,/ /g' ` ; do case "$a_target" in x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; @@ -564,6 +566,7 @@ case "$enableval" in spu) TARGETS_TO_BUILD="CellSPU $TARGETS_TO_BUILD" ;; xcore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;; msp430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;; + hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;; cbe) TARGETS_TO_BUILD="CBackend $TARGETS_TO_BUILD" ;; cpp) TARGETS_TO_BUILD="CppBackend $TARGETS_TO_BUILD" ;; mblaze) TARGETS_TO_BUILD="MBlaze $TARGETS_TO_BUILD" ;; @@ -579,6 +582,7 @@ case "$enableval" in CellSPU|SPU) TARGETS_TO_BUILD="CellSPU $TARGETS_TO_BUILD" ;; XCore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;; MSP430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;; + Hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;; PTX) TARGETS_TO_BUILD="PTX $TARGETS_TO_BUILD" ;; *) AC_MSG_ERROR([Can not set target to build]) ;; esac ;; diff --git a/projects/sample/configure b/projects/sample/configure index dd4305d99c..860faa2927 100755 --- a/projects/sample/configure +++ b/projects/sample/configure @@ -1401,9 +1401,8 @@ Optional Features: (default is YES) --enable-targets Build specific host targets: all or target1,target2,... Valid targets are: host, x86, - x86_64, sparc, powerpc, arm, mips, spu, - xcore, msp430, ptx, cbe, and cpp - (default=all) + x86_64, sparc, powerpc, arm, mips, spu, hexagon, + xcore, msp430, ptx, cbe, and cpp (default=all) --enable-cbe-printf-a Enable C Backend output with hex floating point via %a (default is YES) --enable-bindings Build specific language bindings: @@ -3844,6 +3843,7 @@ else mips-*) llvm_cv_target_arch="Mips" ;; xcore-*) llvm_cv_target_arch="XCore" ;; msp430-*) llvm_cv_target_arch="MSP430" ;; + hexagon-*) llvm_cv_target_arch="Hexagon" ;; mblaze-*) llvm_cv_target_arch="MBlaze" ;; ptx-*) llvm_cv_target_arch="PTX" ;; *) llvm_cv_target_arch="Unknown" ;; @@ -5045,6 +5045,8 @@ else ;; MSP430) TARGET_HAS_JIT=0 ;; + Hexagon) TARGET_HAS_JIT=0 + ;; MBlaze) TARGET_HAS_JIT=0 ;; PTX) TARGET_HAS_JIT=0 @@ -5233,7 +5235,7 @@ if test "$enableval" = host-only ; then enableval=host fi case "$enableval" in - all) TARGETS_TO_BUILD="X86 Sparc PowerPC ARM Mips CellSPU XCore MSP430 CBackend CppBackend MBlaze PTX" ;; + all) TARGETS_TO_BUILD="X86 Sparc PowerPC ARM Mips CellSPU XCore MSP430 Hexagon CBackend CppBackend MBlaze PTX" ;; *)for a_target in `echo $enableval|sed -e 's/,/ /g' ` ; do case "$a_target" in x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; @@ -5245,6 +5247,7 @@ case "$enableval" in spu) TARGETS_TO_BUILD="CellSPU $TARGETS_TO_BUILD" ;; xcore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;; msp430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;; + hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;; cbe) TARGETS_TO_BUILD="CBackend $TARGETS_TO_BUILD" ;; cpp) TARGETS_TO_BUILD="CppBackend $TARGETS_TO_BUILD" ;; mblaze) TARGETS_TO_BUILD="MBlaze $TARGETS_TO_BUILD" ;; @@ -5260,6 +5263,7 @@ case "$enableval" in CellSPU|SPU) TARGETS_TO_BUILD="CellSPU $TARGETS_TO_BUILD" ;; XCore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;; MSP430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;; + Hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;; PTX) TARGETS_TO_BUILD="PTX $TARGETS_TO_BUILD" ;; *) { { echo "$as_me:$LINENO: error: Can not set target to build" >&5 echo "$as_me: error: Can not set target to build" >&2;} diff --git a/test/CodeGen/Hexagon/args.ll b/test/CodeGen/Hexagon/args.ll new file mode 100644 index 0000000000..4ebcaec308 --- /dev/null +++ b/test/CodeGen/Hexagon/args.ll @@ -0,0 +1,18 @@ +; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s +; CHECK: r[[T0:[0-9]+]] = #7 +; CHECK: memw(r29 + #0) = r[[T0]] +; CHECK: r0 = #1 +; CHECK: r1 = #2 +; CHECK: r2 = #3 +; CHECK: r3 = #4 +; CHECK: r4 = #5 +; CHECK: r5 = #6 + + +define void @foo() nounwind { +entry: + call void @bar(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7) + ret void +} + +declare void @bar(i32, i32, i32, i32, i32, i32, i32) diff --git a/test/CodeGen/Hexagon/combine.ll b/test/CodeGen/Hexagon/combine.ll new file mode 100644 index 0000000000..721998596c --- /dev/null +++ b/test/CodeGen/Hexagon/combine.ll @@ -0,0 +1,17 @@ +; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s +; CHECK: combine(r{{[0-9]+}}, r{{[0-9]+}}) + +@j = external global i32 +@k = external global i64 + +define void @foo() nounwind { +entry: + %0 = load i32* @j, align 4 + %1 = load i64* @k, align 8 + %conv = trunc i64 %1 to i32 + %2 = call i64 @llvm.hexagon.A2.combinew(i32 %0, i32 %conv) + store i64 %2, i64* @k, align 8 + ret void +} + +declare i64 @llvm.hexagon.A2.combinew(i32, i32) nounwind readnone diff --git a/test/CodeGen/Hexagon/dg.exp b/test/CodeGen/Hexagon/dg.exp new file mode 100644 index 0000000000..89f45e6723 --- /dev/null +++ b/test/CodeGen/Hexagon/dg.exp @@ -0,0 +1,5 @@ +load_lib llvm.exp + +if { [llvm_supports_target Hexagon] } { + RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]] +} diff --git a/test/CodeGen/Hexagon/double.ll b/test/CodeGen/Hexagon/double.ll new file mode 100644 index 0000000000..c3b6f378ec --- /dev/null +++ b/test/CodeGen/Hexagon/double.ll @@ -0,0 +1,22 @@ +; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s +; CHECK: __hexagon_adddf3 +; CHECK: __hexagon_subdf3 + +define void @foo(double* %acc, double %num, double %num2) nounwind { +entry: + %acc.addr = alloca double*, align 4 + %num.addr = alloca double, align 8 + %num2.addr = alloca double, align 8 + store double* %acc, double** %acc.addr, align 4 + store double %num, double* %num.addr, align 8 + store double %num2, double* %num2.addr, align 8 + %0 = load double** %acc.addr, align 4 + %1 = load double* %0 + %2 = load double* %num.addr, align 8 + %add = fadd double %1, %2 + %3 = load double* %num2.addr, align 8 + %sub = fsub double %add, %3 + %4 = load double** %acc.addr, align 4 + store double %sub, double* %4 + ret void +} diff --git a/test/CodeGen/Hexagon/float.ll b/test/CodeGen/Hexagon/float.ll new file mode 100644 index 0000000000..bec9f5852e --- /dev/null +++ b/test/CodeGen/Hexagon/float.ll @@ -0,0 +1,22 @@ +; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s +; CHECK: __hexagon_addsf3 +; CHECK: __hexagon_subsf3 + +define void @foo(float* %acc, float %num, float %num2) nounwind { +entry: + %acc.addr = alloca float*, align 4 + %num.addr = alloca float, align 4 + %num2.addr = alloca float, align 4 + store float* %acc, float** %acc.addr, align 4 + store float %num, float* %num.addr, align 4 + store float %num2, float* %num2.addr, align 4 + %0 = load float** %acc.addr, align 4 + %1 = load float* %0 + %2 = load float* %num.addr, align 4 + %add = fadd float %1, %2 + %3 = load float* %num2.addr, align 4 + %sub = fsub float %add, %3 + %4 = load float** %acc.addr, align 4 + store float %sub, float* %4 + ret void +} diff --git a/test/CodeGen/Hexagon/frame.ll b/test/CodeGen/Hexagon/frame.ll new file mode 100644 index 0000000000..dc87c732d6 --- /dev/null +++ b/test/CodeGen/Hexagon/frame.ll @@ -0,0 +1,23 @@ +; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s + +@num = external global i32 +@acc = external global i32 +@num2 = external global i32 + +; CHECK: allocframe +; CHECK: dealloc_return + +define i32 @foo() nounwind { +entry: + %i = alloca i32, align 4 + %0 = load i32* @num, align 4 + store i32 %0, i32* %i, align 4 + %1 = load i32* %i, align 4 + %2 = load i32* @acc, align 4 + %mul = mul nsw i32 %1, %2 + %3 = load i32* @num2, align 4 + %add = add nsw i32 %mul, %3 + store i32 %add, i32* %i, align 4 + %4 = load i32* %i, align 4 + ret i32 %4 +} diff --git a/test/CodeGen/Hexagon/mpy.ll b/test/CodeGen/Hexagon/mpy.ll new file mode 100644 index 0000000000..d5c5ae3453 --- /dev/null +++ b/test/CodeGen/Hexagon/mpy.ll @@ -0,0 +1,19 @@ +; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s +; CHECK: += mpyi + +define void @foo(i32 %acc, i32 %num, i32 %num2) nounwind { +entry: + %acc.addr = alloca i32, align 4 + %num.addr = alloca i32, align 4 + %num2.addr = alloca i32, align 4 + store i32 %acc, i32* %acc.addr, align 4 + store i32 %num, i32* %num.addr, align 4 + store i32 %num2, i32* %num2.addr, align 4 + %0 = load i32* %num.addr, align 4 + %1 = load i32* %acc.addr, align 4 + %mul = mul nsw i32 %0, %1 + %2 = load i32* %num2.addr, align 4 + %add = add nsw i32 %mul, %2 + store i32 %add, i32* %num.addr, align 4 + ret void +} diff --git a/test/CodeGen/Hexagon/static.ll b/test/CodeGen/Hexagon/static.ll new file mode 100644 index 0000000000..843b7cbb7a --- /dev/null +++ b/test/CodeGen/Hexagon/static.ll @@ -0,0 +1,20 @@ +; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s + +@num = external global i32 +@acc = external global i32 +@val = external global i32 + +; CHECK: CONST32(#acc) +; CHECK: CONST32(#val) +; CHECK: CONST32(#num) + +define void @foo() nounwind { +entry: + %0 = load i32* @num, align 4 + %1 = load i32* @acc, align 4 + %mul = mul nsw i32 %0, %1 + %2 = load i32* @val, align 4 + %add = add nsw i32 %mul, %2 + store i32 %add, i32* @num, align 4 + ret void +} diff --git a/test/CodeGen/Hexagon/struct_args.ll b/test/CodeGen/Hexagon/struct_args.ll new file mode 100644 index 0000000000..cc409db562 --- /dev/null +++ b/test/CodeGen/Hexagon/struct_args.ll @@ -0,0 +1,15 @@ +; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s +; CHECK: r1:0 = or(r{{[0-9]}}:{{[0-9]}}, r{{[0-9]}}:{{[0-9]}}) + +%struct.small = type { i32, i32 } + +@s1 = common global %struct.small zeroinitializer, align 4 + +define void @foo() nounwind { +entry: + %0 = load i64* bitcast (%struct.small* @s1 to i64*), align 1 + call void @bar(i64 %0) + ret void +} + +declare void @bar(i64) diff --git a/test/CodeGen/Hexagon/struct_args_large.ll b/test/CodeGen/Hexagon/struct_args_large.ll new file mode 100644 index 0000000000..af099cdc43 --- /dev/null +++ b/test/CodeGen/Hexagon/struct_args_large.ll @@ -0,0 +1,16 @@ +; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s +; CHECK: r[[T0:[0-9]+]] = CONST32(#s2) +; CHECK: r[[T1:[0-9]+]] = memw(r[[T0]] + #0) +; CHECK: memw(r29 + #0) = r[[T1]] + +%struct.large = type { i64, i64 } + +@s2 = common global %struct.large zeroinitializer, align 8 + +define void @foo() nounwind { +entry: + call void @bar(%struct.large* byval @s2) + ret void +} + +declare void @bar(%struct.large* byval) diff --git a/test/CodeGen/Hexagon/vaddh.ll b/test/CodeGen/Hexagon/vaddh.ll new file mode 100644 index 0000000000..01d2041097 --- /dev/null +++ b/test/CodeGen/Hexagon/vaddh.ll @@ -0,0 +1,16 @@ +; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s +; CHECK: vaddh(r{{[0-9]+}}, r{{[0-9]+}}) + +@j = external global i32 +@k = external global i32 + +define void @foo() nounwind { +entry: + %0 = load i32* @j, align 4 + %1 = load i32* @k, align 4 + %2 = call i32 @llvm.hexagon.A2.svaddh(i32 %0, i32 %1) + store i32 %2, i32* @k, align 4 + ret void +} + +declare i32 @llvm.hexagon.A2.svaddh(i32, i32) nounwind readnone |