diff options
author | Walter Lee <walt@tilera.com> | 2014-02-24 15:08:00 +0000 |
---|---|---|
committer | Walter Lee <walt@gcc.gnu.org> | 2014-02-24 15:08:00 +0000 |
commit | 341c653c704e398070219534cd9fed97e56661b3 (patch) | |
tree | 53162bb2cdbb19111069e925e278cefd4d970326 /gcc | |
parent | c97d7285d9b949ac05ad04f0d76112579c50e240 (diff) | |
download | gcc-341c653c704e398070219534cd9fed97e56661b3.zip gcc-341c653c704e398070219534cd9fed97e56661b3.tar.gz gcc-341c653c704e398070219534cd9fed97e56661b3.tar.bz2 |
TILE-Gx big endian support.
/:
* configure.ac (tilepro-*-*) Change to tilepro*-*-*.
(tilegx-*-*): Change to tilegx*-*-*.
* configure: Regenerate.
contrib/:
* config-list.mk (LIST): Add tilegxbe-linux-gnu.
libcpp/:
* configure.ac: Change "tilepro" triplet to "tilepro*".
* configure: Regenerate.
libgcc/:
* config.host: Support "tilegx*" and "tilepro*" triplets.
* config/tilegx/sfp-machine32.h (__BYTE_ORDER): Handle big endian.
* config/tilegx/sfp-machine64.h (__BYTE_ORDER): Handle big endian.
gcc/:
* config.gcc (tilepro-*-*): Change to tilepro*-*-*.
(tilegx-*-linux*): Change to tilegx*-*-linux*; Support tilegxbe
triplet.
* common/config/tilegx/tilegx-common.c
(TARGET_DEFAULT_TARGET_FLAGS): Define.
* config/tilegx/linux.h (ASM_SPEC): Add endian_spec.
(LINK_SPEC): Ditto.
* config/tilegx/sync.md (atomic_test_and_set): Handle big endian.
* config/tilegx/tilegx.c (tilegx_return_in_msb): New.
(tilegx_gimplify_va_arg_expr): Handle big endian.
(tilegx_expand_unaligned_load): Ditto.
(tilegx_expand_unaligned_store): Ditto.
(TARGET_RETURN_IN_MSB): New.
* config/tilegx/tilegx.h (TARGET_DEFAULT): New.
(TARGET_ENDIAN_DEFAULT): New.
(TARGET_BIG_ENDIAN): Handle big endian.
(BYTES_BIG_ENDIAN): Ditto.
(WORDS_BIG_ENDIAN): Ditto.
(FLOAT_WORDS_BIG_ENDIAN): Ditto.
(ENDIAN_SPEC): New.
(EXTRA_SPECS): New.
* config/tilegx/tilegx.md (extv): Handle big endian.
(extzv): Ditto.
(insn_st<n>): Ditto.
(insn_st<n>_add<bitsuffix>): Ditto.
(insn_stnt<n>): Ditto.
(insn_stnt<n>_add<bitsuffix>):Ditto.
(vec_interleave_highv8qi): Handle big endian.
(vec_interleave_highv8qi_be): New.
(vec_interleave_highv8qi_le): New.
(insn_v1int_h): Handle big endian.
(vec_interleave_lowv8qi): Handle big endian.
(vec_interleave_lowv8qi_be): New.
(vec_interleave_lowv8qi_le): New.
(insn_v1int_l): Handle big endian.
(vec_interleave_highv4hi): Handle big endian.
(vec_interleave_highv4hi_be): New.
(vec_interleave_highv4hi_le): New.
(insn_v2int_h): Handle big endian.
(vec_interleave_lowv4hi): Handle big endian.
(vec_interleave_lowv4hi_be): New.
(vec_interleave_lowv4hi_le): New.
(insn_v2int_l): Handle big endian.
(vec_interleave_highv2si): Handle big endian.
(vec_interleave_highv2si_be): New.
(vec_interleave_highv2si_le): New.
(insn_v4int_h): Handle big endian.
(vec_interleave_lowv2si): Handle big endian.
(vec_interleave_lowv2si_be): New.
(vec_interleave_lowv2si_le): New.
(insn_v4int_l): Handle big endian.
* config/tilegx/tilegx.opt (mbig-endian): New option.
(mlittle-endian): New option.
* doc/install.texi: Document tilegxbe-linux.
* doc/invoke.texi: Document -mbig-endian and -mlittle-endian.
From-SVN: r208069
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 58 | ||||
-rw-r--r-- | gcc/common/config/tilegx/tilegx-common.c | 5 | ||||
-rw-r--r-- | gcc/config.gcc | 11 | ||||
-rw-r--r-- | gcc/config/tilegx/linux.h | 5 | ||||
-rw-r--r-- | gcc/config/tilegx/sync.md | 28 | ||||
-rw-r--r-- | gcc/config/tilegx/tilegx.c | 74 | ||||
-rw-r--r-- | gcc/config/tilegx/tilegx.h | 40 | ||||
-rw-r--r-- | gcc/config/tilegx/tilegx.md | 281 | ||||
-rw-r--r-- | gcc/config/tilegx/tilegx.opt | 8 | ||||
-rw-r--r-- | gcc/doc/install.texi | 14 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 9 |
11 files changed, 459 insertions, 74 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6ca0b17..6371f2b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,61 @@ +2014-02-24 Walter Lee <walt@tilera.com> + + * config.gcc (tilepro-*-*): Change to tilepro*-*-*. + (tilegx-*-linux*): Change to tilegx*-*-linux*; Support tilegxbe + triplet. + * common/config/tilegx/tilegx-common.c + (TARGET_DEFAULT_TARGET_FLAGS): Define. + * config/tilegx/linux.h (ASM_SPEC): Add endian_spec. + (LINK_SPEC): Ditto. + * config/tilegx/sync.md (atomic_test_and_set): Handle big endian. + * config/tilegx/tilegx.c (tilegx_return_in_msb): New. + (tilegx_gimplify_va_arg_expr): Handle big endian. + (tilegx_expand_unaligned_load): Ditto. + (tilegx_expand_unaligned_store): Ditto. + (TARGET_RETURN_IN_MSB): New. + * config/tilegx/tilegx.h (TARGET_DEFAULT): New. + (TARGET_ENDIAN_DEFAULT): New. + (TARGET_BIG_ENDIAN): Handle big endian. + (BYTES_BIG_ENDIAN): Ditto. + (WORDS_BIG_ENDIAN): Ditto. + (FLOAT_WORDS_BIG_ENDIAN): Ditto. + (ENDIAN_SPEC): New. + (EXTRA_SPECS): New. + * config/tilegx/tilegx.md (extv): Handle big endian. + (extzv): Ditto. + (insn_st<n>): Ditto. + (insn_st<n>_add<bitsuffix>): Ditto. + (insn_stnt<n>): Ditto. + (insn_stnt<n>_add<bitsuffix>):Ditto. + (vec_interleave_highv8qi): Handle big endian. + (vec_interleave_highv8qi_be): New. + (vec_interleave_highv8qi_le): New. + (insn_v1int_h): Handle big endian. + (vec_interleave_lowv8qi): Handle big endian. + (vec_interleave_lowv8qi_be): New. + (vec_interleave_lowv8qi_le): New. + (insn_v1int_l): Handle big endian. + (vec_interleave_highv4hi): Handle big endian. + (vec_interleave_highv4hi_be): New. + (vec_interleave_highv4hi_le): New. + (insn_v2int_h): Handle big endian. + (vec_interleave_lowv4hi): Handle big endian. + (vec_interleave_lowv4hi_be): New. + (vec_interleave_lowv4hi_le): New. + (insn_v2int_l): Handle big endian. + (vec_interleave_highv2si): Handle big endian. + (vec_interleave_highv2si_be): New. + (vec_interleave_highv2si_le): New. + (insn_v4int_h): Handle big endian. + (vec_interleave_lowv2si): Handle big endian. + (vec_interleave_lowv2si_be): New. + (vec_interleave_lowv2si_le): New. + (insn_v4int_l): Handle big endian. + * config/tilegx/tilegx.opt (mbig-endian): New option. + (mlittle-endian): New option. + * doc/install.texi: Document tilegxbe-linux. + * doc/invoke.texi: Document -mbig-endian and -mlittle-endian. + 2014-02-24 Martin Jambor <mjambor@suse.cz> PR ipa/60266 diff --git a/gcc/common/config/tilegx/tilegx-common.c b/gcc/common/config/tilegx/tilegx-common.c index 6294f7d..ad6fdba 100644 --- a/gcc/common/config/tilegx/tilegx-common.c +++ b/gcc/common/config/tilegx/tilegx-common.c @@ -45,6 +45,11 @@ tilegx_option_init_struct (struct gcc_options *opts) } +#undef TARGET_DEFAULT_TARGET_FLAGS +#define TARGET_DEFAULT_TARGET_FLAGS \ + (TARGET_DEFAULT \ + | TARGET_ENDIAN_DEFAULT) + #undef TARGET_OPTION_OPTIMIZATION_TABLE #define TARGET_OPTION_OPTIMIZATION_TABLE tilegx_option_optimization_table diff --git a/gcc/config.gcc b/gcc/config.gcc index 2156640..2a3deae 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -494,7 +494,7 @@ tilegx*-*-*) cpu_type=tilegx need_64bit_hwint=yes ;; -tilepro-*-*) +tilepro*-*-*) cpu_type=tilepro need_64bit_hwint=yes ;; @@ -2764,15 +2764,20 @@ tic6x-*-uclinux) tmake_file="${tmake_file} c6x/t-c6x c6x/t-c6x-elf c6x/t-c6x-uclinux" use_collect2=no ;; -tilegx-*-linux*) +tilegx*-*-linux*) tm_file="elfos.h gnu-user.h linux.h glibc-stdint.h tilegx/linux.h ${tm_file}" tmake_file="${tmake_file} tilegx/t-tilegx" extra_objs="${extra_objs} mul-tables.o" c_target_objs="${c_target_objs} tilegx-c.o" cxx_target_objs="${cxx_target_objs} tilegx-c.o" extra_headers="feedback.h" + case $target in + tilegxbe-*) + tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=1" + ;; + esac ;; -tilepro-*-linux*) +tilepro*-*-linux*) tm_file="elfos.h gnu-user.h linux.h glibc-stdint.h tilepro/linux.h ${tm_file}" tmake_file="${tmake_file} tilepro/t-tilepro" extra_objs="${extra_objs} mul-tables.o" diff --git a/gcc/config/tilegx/linux.h b/gcc/config/tilegx/linux.h index 02bc050..8cdedcb 100644 --- a/gcc/config/tilegx/linux.h +++ b/gcc/config/tilegx/linux.h @@ -22,10 +22,11 @@ #define CPP_SPEC "%{pthread:-D_REENTRANT}" #undef ASM_SPEC -#define ASM_SPEC "%{m32:--32} %{m64:--64}" +#define ASM_SPEC "%(endian_spec) %{m32:--32} %{m64:--64}" #undef LINK_SPEC -#define LINK_SPEC "%{m64:-m elf64tilegx} %{m32:-m elf32tilegx} \ +#define LINK_SPEC "%(endian_spec) \ + %{m64:-m elf64tilegx} %{m32:-m elf32tilegx} \ %{shared:-shared} \ %{!shared: \ %{!static: \ diff --git a/gcc/config/tilegx/sync.md b/gcc/config/tilegx/sync.md index 3d93493..b32b662 100644 --- a/gcc/config/tilegx/sync.md +++ b/gcc/config/tilegx/sync.md @@ -177,8 +177,7 @@ (match_operand:SI 2 "const_int_operand" "")] ;; model "" { - rtx addr, aligned_addr, aligned_mem, offset, word, shmt; - rtx tmp0, tmp1; + rtx addr, aligned_addr, aligned_mem, offset, word, shmt, tmp; rtx result = operands[0]; rtx mem = operands[1]; enum memmodel model = (enum memmodel) INTVAL (operands[2]); @@ -191,27 +190,38 @@ aligned_mem = change_address (mem, DImode, aligned_addr); set_mem_alias_set (aligned_mem, 0); + tmp = gen_reg_rtx (Pmode); + if (BYTES_BIG_ENDIAN) + { + emit_move_insn (gen_lowpart (DImode, tmp), + gen_rtx_NOT (DImode, gen_lowpart (DImode, addr))); + } + else + { + tmp = addr; + } + offset = gen_reg_rtx (DImode); - emit_move_insn (offset, gen_rtx_AND (DImode, gen_lowpart (DImode, addr), + emit_move_insn (offset, gen_rtx_AND (DImode, gen_lowpart (DImode, tmp), GEN_INT (7))); - tmp0 = gen_reg_rtx (DImode); - emit_move_insn (tmp0, GEN_INT (1)); + tmp = gen_reg_rtx (DImode); + emit_move_insn (tmp, GEN_INT (1)); shmt = gen_reg_rtx (DImode); emit_move_insn (shmt, gen_rtx_ASHIFT (DImode, offset, GEN_INT (3))); word = gen_reg_rtx (DImode); - emit_move_insn (word, gen_rtx_ASHIFT (DImode, tmp0, + emit_move_insn (word, gen_rtx_ASHIFT (DImode, tmp, gen_lowpart (SImode, shmt))); - tmp1 = gen_reg_rtx (DImode); + tmp = gen_reg_rtx (DImode); tilegx_pre_atomic_barrier (model); - emit_insn (gen_atomic_fetch_or_baredi (tmp1, aligned_mem, word)); + emit_insn (gen_atomic_fetch_or_baredi (tmp, aligned_mem, word)); tilegx_post_atomic_barrier (model); emit_move_insn (gen_lowpart (DImode, result), - gen_rtx_LSHIFTRT (DImode, tmp1, + gen_rtx_LSHIFTRT (DImode, tmp, gen_lowpart (SImode, shmt))); DONE; }) diff --git a/gcc/config/tilegx/tilegx.c b/gcc/config/tilegx/tilegx.c index f3c68e3..c3b7126 100644 --- a/gcc/config/tilegx/tilegx.c +++ b/gcc/config/tilegx/tilegx.c @@ -175,6 +175,17 @@ tilegx_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED, } +/* Implement TARGET_RETURN_IN_MSB. We return a value in the most + significant part of a register if: + - the target is big-endian; and + - the value has an aggregate type (e.g., structure or union). */ +static bool +tilegx_return_in_msb (const_tree valtype) +{ + return (TARGET_BIG_ENDIAN && AGGREGATE_TYPE_P (valtype)); +} + + /* Implement TARGET_RETURN_IN_MEMORY. */ static bool tilegx_return_in_memory (const_tree type, const_tree fndecl ATTRIBUTE_UNUSED) @@ -440,7 +451,10 @@ tilegx_setup_incoming_varargs (cumulative_args_t cum, else addr = VALIST.__args; VALIST.__args = addr + paddedsize; - ret = *(TYPE *)addr; + if (BYTES_BIG_ENDIAN) + ret = *(TYPE *)(addr + paddedsize - sizeof(TYPE)); + else + ret = *(TYPE *)addr; */ static tree tilegx_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p, @@ -503,10 +517,17 @@ tilegx_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p, size_int (STACK_POINTER_OFFSET)), unshare_expr (args)); + /* Adjust the address of va_arg if it is in big endian mode. */ + if (BYTES_BIG_ENDIAN && rsize > size) + tmp = fold_build_pointer_plus_hwi (tmp, rsize - size); gimplify_assign (addr, tmp, pre_p); /* Update VALIST.__args. */ - tmp = fold_build_pointer_plus_hwi (addr, rsize); + + if (BYTES_BIG_ENDIAN && rsize > size) + tmp = fold_build_pointer_plus_hwi (addr, size); + else + tmp = fold_build_pointer_plus_hwi (addr, rsize); gimplify_assign (unshare_expr (args), tmp, pre_p); addr = fold_convert (build_pointer_type (type), addr); @@ -1847,39 +1868,51 @@ tilegx_expand_unaligned_load (rtx dest_reg, rtx mem, HOST_WIDE_INT bitsize, mode = GET_MODE (dest_reg); - hi = gen_reg_rtx (mode); - if (bitsize == 2 * BITS_PER_UNIT && (bit_offset % BITS_PER_UNIT) == 0) { + rtx mem_left, mem_right; + rtx left = gen_reg_rtx (mode); + /* When just loading a two byte value, we can load the two bytes individually and combine them efficiently. */ mem_lo = adjust_address (mem, QImode, byte_offset); mem_hi = adjust_address (mem, QImode, byte_offset + 1); + if (BYTES_BIG_ENDIAN) + { + mem_left = mem_lo; + mem_right = mem_hi; + } + else + { + mem_left = mem_hi; + mem_right = mem_lo; + } + if (sign) { /* Do a signed load of the second byte and use bfins to set the high bits of the result. */ emit_insn (gen_zero_extendqidi2 (gen_lowpart (DImode, dest_reg), - mem_lo)); - emit_insn (gen_extendqidi2 (gen_lowpart (DImode, hi), mem_hi)); + mem_right)); + emit_insn (gen_extendqidi2 (gen_lowpart (DImode, left), mem_left)); emit_insn (gen_insv (gen_lowpart (DImode, dest_reg), GEN_INT (64 - 8), GEN_INT (8), - gen_lowpart (DImode, hi))); + gen_lowpart (DImode, left))); } else { /* Do two unsigned loads and use v1int_l to interleave them. */ - rtx lo = gen_reg_rtx (mode); - emit_insn (gen_zero_extendqidi2 (gen_lowpart (DImode, lo), - mem_lo)); - emit_insn (gen_zero_extendqidi2 (gen_lowpart (DImode, hi), - mem_hi)); + rtx right = gen_reg_rtx (mode); + emit_insn (gen_zero_extendqidi2 (gen_lowpart (DImode, right), + mem_right)); + emit_insn (gen_zero_extendqidi2 (gen_lowpart (DImode, left), + mem_left)); emit_insn (gen_insn_v1int_l (gen_lowpart (DImode, dest_reg), - gen_lowpart (DImode, hi), - gen_lowpart (DImode, lo))); + gen_lowpart (DImode, left), + gen_lowpart (DImode, right))); } return; @@ -1917,6 +1950,7 @@ tilegx_expand_unaligned_load (rtx dest_reg, rtx mem, HOST_WIDE_INT bitsize, } /* Load hi first in case dest_reg is used in mema. */ + hi = gen_reg_rtx (mode); emit_move_insn (hi, mem_hi); emit_move_insn (wide_result, mem_lo); @@ -1945,12 +1979,17 @@ tilegx_expand_unaligned_store (rtx mem, rtx src, HOST_WIDE_INT bitsize, { HOST_WIDE_INT byte_offset = bit_offset / BITS_PER_UNIT; HOST_WIDE_INT bytesize = bitsize / BITS_PER_UNIT; - HOST_WIDE_INT shift_amt; + HOST_WIDE_INT shift_init, shift_increment, shift_amt; HOST_WIDE_INT i; rtx mem_addr; rtx store_val; - for (i = 0, shift_amt = 0; i < bytesize; i++, shift_amt += BITS_PER_UNIT) + shift_init = BYTES_BIG_ENDIAN ? (bitsize - BITS_PER_UNIT) : 0; + shift_increment = BYTES_BIG_ENDIAN ? -BITS_PER_UNIT : BITS_PER_UNIT; + + for (i = 0, shift_amt = shift_init; + i < bytesize; + i++, shift_amt += shift_increment) { mem_addr = adjust_address (mem, QImode, byte_offset + i); @@ -5530,6 +5569,9 @@ tilegx_file_end (void) #undef TARGET_PASS_BY_REFERENCE #define TARGET_PASS_BY_REFERENCE tilegx_pass_by_reference +#undef TARGET_RETURN_IN_MSB +#define TARGET_RETURN_IN_MSB tilegx_return_in_msb + #undef TARGET_RETURN_IN_MEMORY #define TARGET_RETURN_IN_MEMORY tilegx_return_in_memory diff --git a/gcc/config/tilegx/tilegx.h b/gcc/config/tilegx/tilegx.h index 9eab51e..f241fe4 100644 --- a/gcc/config/tilegx/tilegx.h +++ b/gcc/config/tilegx/tilegx.h @@ -18,6 +18,23 @@ along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ +/* Default target_flags if no switches are specified */ +#ifndef TARGET_DEFAULT +#define TARGET_DEFAULT 0 +#endif + +#ifndef TARGET_BIG_ENDIAN_DEFAULT +#define TARGET_BIG_ENDIAN_DEFAULT 0 +#endif + +#ifndef TARGET_ENDIAN_DEFAULT +#if TARGET_BIG_ENDIAN_DEFAULT +#define TARGET_ENDIAN_DEFAULT MASK_BIG_ENDIAN +#else +#define TARGET_ENDIAN_DEFAULT 0 +#endif +#endif + /* This is used by tilegx_cpu_cpp_builtins to indicate the byte order we're compiling for. */ #define TILEGX_CPU_CPP_ENDIAN_BUILTINS() \ @@ -52,10 +69,10 @@ /* Target machine storage layout */ -#define TARGET_BIG_ENDIAN 0 #define BITS_BIG_ENDIAN 0 -#define BYTES_BIG_ENDIAN TARGET_BIG_ENDIAN -#define WORDS_BIG_ENDIAN TARGET_BIG_ENDIAN +#define BYTES_BIG_ENDIAN (TARGET_BIG_ENDIAN != 0) +#define WORDS_BIG_ENDIAN (TARGET_BIG_ENDIAN != 0) +#define FLOAT_WORDS_BIG_ENDIAN (TARGET_BIG_ENDIAN != 0) #define UNITS_PER_WORD 8 #define PARM_BOUNDARY BITS_PER_WORD @@ -520,3 +537,20 @@ typedef struct GTY(()) machine_function #ifndef HAVE_AS_TLS #define HAVE_AS_TLS 0 #endif + +#ifndef ENDIAN_SPEC +#if TARGET_BIG_ENDIAN_DEFAULT +#define ENDIAN_SPEC \ + "%{!mlittle-endian:-EB} \ + %{mlittle-endian:%{mbig-endian: \ + %e-mbig-endian and -mlittle-endian may not be used together}-EL}" +#else +#define ENDIAN_SPEC \ + "%{!mbig-endian:-EL} \ + %{mbig-endian:%{mlittle-endian: \ + %e-mbig-endian and -mlittle-endian may not be used together}-EB}" +#endif +#endif + +#define EXTRA_SPECS \ + { "endian_spec", ENDIAN_SPEC } diff --git a/gcc/config/tilegx/tilegx.md b/gcc/config/tilegx/tilegx.md index c8c7af6..94946bb 100644 --- a/gcc/config/tilegx/tilegx.md +++ b/gcc/config/tilegx/tilegx.md @@ -824,6 +824,12 @@ bit_width = INTVAL (operands[2]); bit_offset = INTVAL (operands[3]); + /* NOTE: bit_offset is relative to the mode of operand + 1 (QImode). It will be negative in big-endian mode + here. Convert that back to the real offset. */ + if (BYTES_BIG_ENDIAN) + bit_offset = GET_MODE_BITSIZE (QImode) - bit_width - bit_offset; + /* Reject bitfields that can be done with a normal load. */ if (MEM_ALIGN (operands[1]) >= bit_offset + bit_width) FAIL; @@ -860,6 +866,12 @@ if (GET_MODE (operands[1]) != QImode) FAIL; + /* NOTE: bit_offset is relative to the mode of operand + 1 (QImode). It will be negative in big-endian mode + here. */ + if (BYTES_BIG_ENDIAN) + bit_offset = GET_MODE_BITSIZE (QImode) - bit_width - bit_offset; + /* Reject bitfields that can be done with a normal load. */ if (MEM_ALIGN (operands[1]) >= bit_offset + bit_width) FAIL; @@ -3983,7 +3995,9 @@ (match_operand:DI 1 "reg_or_0_operand" ""))] "" { - operands[1] = simplify_gen_subreg (<MODE>mode, operands[1], DImode, 0); + operands[1] = simplify_gen_subreg (<MODE>mode, operands[1], DImode, + BYTES_BIG_ENDIAN + ? UNITS_PER_WORD - <n> : 0); }) (define_expand "insn_st<I124MODE:n>_add<I48MODE:bitsuffix>" @@ -3996,7 +4010,9 @@ "" { operands[1] = simplify_gen_subreg (<I124MODE:MODE>mode, operands[1], - DImode, 0); + DImode, + BYTES_BIG_ENDIAN + ? UNITS_PER_WORD - <I124MODE:n> : 0); }) (define_insn "*insn_st<I124MODE:n>_add<I48MODE:bitsuffix>" @@ -4035,7 +4051,9 @@ (match_operand:DI 1 "reg_or_0_operand" ""))] "" { - operands[1] = simplify_gen_subreg (<MODE>mode, operands[1], DImode, 0); + operands[1] = simplify_gen_subreg (<MODE>mode, operands[1], DImode, + BYTES_BIG_ENDIAN + ? UNITS_PER_WORD - <n> : 0); }) (define_insn "*insn_stnt<n>" @@ -4056,7 +4074,9 @@ "" { operands[1] = simplify_gen_subreg (<I124MODE:MODE>mode, operands[1], - DImode, 0); + DImode, + BYTES_BIG_ENDIAN + ? UNITS_PER_WORD - <n> : 0); }) (define_insn "*insn_stnt<I124MODE:n>_add<I48MODE:bitsuffix>" @@ -4412,11 +4432,46 @@ DONE; }) +;; Byte ordering of these vectors is endian dependent. gcc concats +;; right-to-left for little endian, and left-to-right for big endian. +;; So we need different patterns that depend on endianness. Our +;; instructions concat and interleave the way a big-endian target would +;; work in gcc, so for little endian, we need to reverse the source +;; operands. + ;; insn_v1int_h ;; {B7,B6,B5,B4,B3,B2,B1,B0} {A7,A6,A5,A4,A3,A2,A1,A0} ;; => {A7,A6,A5,A4,A3,A2,A1,A0,B7,B6,B5,B4,B3,B2,B1,B0} ;; => {A7,B7,A6,B6,A5,B5,A4,B4} -(define_insn "vec_interleave_highv8qi" +(define_expand "vec_interleave_highv8qi" + [(match_operand:V8QI 0 "register_operand" "") + (match_operand:V8QI 1 "reg_or_0_operand" "") + (match_operand:V8QI 2 "reg_or_0_operand" "")] + "" +{ + if (BYTES_BIG_ENDIAN) + emit_insn (gen_vec_interleave_highv8qi_be (operands[0], operands[1], + operands[2])); + else + emit_insn (gen_vec_interleave_highv8qi_le (operands[0], operands[1], + operands[2])); + DONE; +}) + +(define_insn "vec_interleave_highv8qi_be" + [(set (match_operand:V8QI 0 "register_operand" "=r") + (vec_select:V8QI + (vec_concat:V16QI (match_operand:V8QI 1 "reg_or_0_operand" "rO") + (match_operand:V8QI 2 "reg_or_0_operand" "rO")) + (parallel [(const_int 0) (const_int 8) + (const_int 1) (const_int 9) + (const_int 2) (const_int 10) + (const_int 3) (const_int 11)])))] + "BYTES_BIG_ENDIAN" + "v1int_h\t%0, %r1, %r2" + [(set_attr "type" "X01")]) + +(define_insn "vec_interleave_highv8qi_le" [(set (match_operand:V8QI 0 "register_operand" "=r") (vec_select:V8QI (vec_concat:V16QI (match_operand:V8QI 1 "reg_or_0_operand" "rO") @@ -4425,7 +4480,7 @@ (const_int 5) (const_int 13) (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))] - "" + "!BYTES_BIG_ENDIAN" "v1int_h\t%0, %r2, %r1" [(set_attr "type" "X01")]) @@ -4435,11 +4490,14 @@ (match_operand:DI 2 "reg_or_0_operand" "")] "" { - /* Our instruction interleaves opposite of the way vec_interleave - works, so we need to reverse the source operands. */ + /* For little endian, our instruction interleaves opposite of the + way vec_interleave works, so we need to reverse the source + operands. */ + rtx opnd1 = BYTES_BIG_ENDIAN ? operands[1] : operands[2]; + rtx opnd2 = BYTES_BIG_ENDIAN ? operands[2] : operands[1]; tilegx_expand_builtin_vector_binop (gen_vec_interleave_highv8qi, V8QImode, - operands[0], V8QImode, operands[2], - operands[1], true); + operands[0], V8QImode, opnd1, opnd2, + true); DONE; }) @@ -4447,7 +4505,35 @@ ;; {B7,B6,B5,B4,B3,B2,B1,B0} {A7,A6,A5,A4,A3,A2,A1,A0} ;; => {A7,A6,A5,A4,A3,A2,A1,A0,B7,B6,B5,B4,B3,B2,B1,B0} ;; => {A3,B3,A2,B2,A1,B1,A0,B0} -(define_insn "vec_interleave_lowv8qi" +(define_expand "vec_interleave_lowv8qi" + [(match_operand:V8QI 0 "register_operand" "") + (match_operand:V8QI 1 "reg_or_0_operand" "") + (match_operand:V8QI 2 "reg_or_0_operand" "")] + "" +{ + if (BYTES_BIG_ENDIAN) + emit_insn (gen_vec_interleave_lowv8qi_be (operands[0], operands[1], + operands[2])); + else + emit_insn (gen_vec_interleave_lowv8qi_le (operands[0], operands[1], + operands[2])); + DONE; +}) + +(define_insn "vec_interleave_lowv8qi_be" + [(set (match_operand:V8QI 0 "register_operand" "=r") + (vec_select:V8QI + (vec_concat:V16QI (match_operand:V8QI 1 "reg_or_0_operand" "rO") + (match_operand:V8QI 2 "reg_or_0_operand" "rO")) + (parallel [(const_int 4) (const_int 12) + (const_int 5) (const_int 13) + (const_int 6) (const_int 14) + (const_int 7) (const_int 15)])))] + "BYTES_BIG_ENDIAN" + "v1int_l\t%0, %r1, %r2" + [(set_attr "type" "X01")]) + +(define_insn "vec_interleave_lowv8qi_le" [(set (match_operand:V8QI 0 "register_operand" "=r") (vec_select:V8QI (vec_concat:V16QI (match_operand:V8QI 1 "reg_or_0_operand" "rO") @@ -4456,7 +4542,7 @@ (const_int 1) (const_int 9) (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))] - "" + "!BYTES_BIG_ENDIAN" "v1int_l\t%0, %r2, %r1" [(set_attr "type" "X01")]) @@ -4466,11 +4552,14 @@ (match_operand:DI 2 "reg_or_0_operand" "")] "" { - /* Our instruction interleaves opposite of the way vec_interleave - works, so we need to reverse the source operands. */ + /* For little endian, our instruction interleaves opposite of the + way vec_interleave works, so we need to reverse the source + operands. */ + rtx opnd1 = BYTES_BIG_ENDIAN ? operands[1] : operands[2]; + rtx opnd2 = BYTES_BIG_ENDIAN ? operands[2] : operands[1]; tilegx_expand_builtin_vector_binop (gen_vec_interleave_lowv8qi, V8QImode, - operands[0], V8QImode, operands[2], - operands[1], true); + operands[0], V8QImode, opnd1, opnd2, + true); DONE; }) @@ -4478,14 +4567,40 @@ ;; {B3,B2,B1,B0} {A3,A2,A1,A0} ;; => {A3,A2,A1,A0,B3,B2,B1,B0} ;; => {A3,B3,A2,B2} -(define_insn "vec_interleave_highv4hi" +(define_expand "vec_interleave_highv4hi" + [(match_operand:V4HI 0 "register_operand" "") + (match_operand:V4HI 1 "reg_or_0_operand" "") + (match_operand:V4HI 2 "reg_or_0_operand" "")] + "" +{ + if (BYTES_BIG_ENDIAN) + emit_insn (gen_vec_interleave_highv4hi_be (operands[0], operands[1], + operands[2])); + else + emit_insn (gen_vec_interleave_highv4hi_le (operands[0], operands[1], + operands[2])); + DONE; +}) + +(define_insn "vec_interleave_highv4hi_be" + [(set (match_operand:V4HI 0 "register_operand" "=r") + (vec_select:V4HI + (vec_concat:V8HI (match_operand:V4HI 1 "reg_or_0_operand" "rO") + (match_operand:V4HI 2 "reg_or_0_operand" "rO")) + (parallel [(const_int 0) (const_int 4) + (const_int 1) (const_int 5)])))] + "BYTES_BIG_ENDIAN" + "v2int_h\t%0, %r1, %r2" + [(set_attr "type" "X01")]) + +(define_insn "vec_interleave_highv4hi_le" [(set (match_operand:V4HI 0 "register_operand" "=r") (vec_select:V4HI (vec_concat:V8HI (match_operand:V4HI 1 "reg_or_0_operand" "rO") (match_operand:V4HI 2 "reg_or_0_operand" "rO")) (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))] - "" + "!BYTES_BIG_ENDIAN" "v2int_h\t%0, %r2, %r1" [(set_attr "type" "X01")]) @@ -4495,11 +4610,14 @@ (match_operand:DI 2 "reg_or_0_operand" "")] "" { - /* Our instruction interleaves opposite of the way vec_interleave - works, so we need to reverse the source operands. */ + /* For little endian, our instruction interleaves opposite of the + way vec_interleave works, so we need to reverse the source + operands. */ + rtx opnd1 = BYTES_BIG_ENDIAN ? operands[1] : operands[2]; + rtx opnd2 = BYTES_BIG_ENDIAN ? operands[2] : operands[1]; tilegx_expand_builtin_vector_binop (gen_vec_interleave_highv4hi, V4HImode, - operands[0], V4HImode, operands[2], - operands[1], true); + operands[0], V4HImode, opnd1, opnd2, + true); DONE; }) @@ -4507,14 +4625,40 @@ ;; {B3,B2,B1,B0} {A3,A2,A1,A0} ;; => {A3,A2,A1,A0,B3,B2,B1,B0} ;; => {A1,B1,A0,B0} -(define_insn "vec_interleave_lowv4hi" +(define_expand "vec_interleave_lowv4hi" + [(match_operand:V4HI 0 "register_operand" "") + (match_operand:V4HI 1 "reg_or_0_operand" "") + (match_operand:V4HI 2 "reg_or_0_operand" "")] + "" +{ + if (BYTES_BIG_ENDIAN) + emit_insn (gen_vec_interleave_lowv4hi_be (operands[0], operands[1], + operands[2])); + else + emit_insn (gen_vec_interleave_lowv4hi_le (operands[0], operands[1], + operands[2])); + DONE; +}) + +(define_insn "vec_interleave_lowv4hi_be" + [(set (match_operand:V4HI 0 "register_operand" "=r") + (vec_select:V4HI + (vec_concat:V8HI (match_operand:V4HI 1 "reg_or_0_operand" "rO") + (match_operand:V4HI 2 "reg_or_0_operand" "rO")) + (parallel [(const_int 2) (const_int 6) + (const_int 3) (const_int 7)])))] + "BYTES_BIG_ENDIAN" + "v2int_l\t%0, %r1, %r2" + [(set_attr "type" "X01")]) + +(define_insn "vec_interleave_lowv4hi_le" [(set (match_operand:V4HI 0 "register_operand" "=r") (vec_select:V4HI (vec_concat:V8HI (match_operand:V4HI 1 "reg_or_0_operand" "rO") (match_operand:V4HI 2 "reg_or_0_operand" "rO")) (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))] - "" + "!BYTES_BIG_ENDIAN" "v2int_l\t%0, %r2, %r1" [(set_attr "type" "X01")]) @@ -4524,9 +4668,14 @@ (match_operand:DI 2 "reg_or_0_operand" "")] "" { + /* For little endian, our instruction interleaves opposite of the + way vec_interleave works, so we need to reverse the source + operands. */ + rtx opnd1 = BYTES_BIG_ENDIAN ? operands[1] : operands[2]; + rtx opnd2 = BYTES_BIG_ENDIAN ? operands[2] : operands[1]; tilegx_expand_builtin_vector_binop (gen_vec_interleave_lowv4hi, V4HImode, - operands[0], V4HImode, operands[2], - operands[1], true); + operands[0], V4HImode, opnd1, opnd2, + true); DONE; }) @@ -4534,13 +4683,38 @@ ;; {B1,B0} {A1,A0} ;; => {A1,A0,B1,B0} ;; => {A1,B1} -(define_insn "vec_interleave_highv2si" +(define_expand "vec_interleave_highv2si" + [(match_operand:V2SI 0 "register_operand" "") + (match_operand:V2SI 1 "reg_or_0_operand" "") + (match_operand:V2SI 2 "reg_or_0_operand" "")] + "" +{ + if (BYTES_BIG_ENDIAN) + emit_insn (gen_vec_interleave_highv2si_be (operands[0], operands[1], + operands[2])); + else + emit_insn (gen_vec_interleave_highv2si_le (operands[0], operands[1], + operands[2])); + DONE; +}) + +(define_insn "vec_interleave_highv2si_be" + [(set (match_operand:V2SI 0 "register_operand" "=r") + (vec_select:V2SI + (vec_concat:V4SI (match_operand:V2SI 1 "reg_or_0_operand" "rO") + (match_operand:V2SI 2 "reg_or_0_operand" "rO")) + (parallel [(const_int 0) (const_int 2)])))] + "BYTES_BIG_ENDIAN" + "v4int_h\t%0, %r1, %r2" + [(set_attr "type" "X01")]) + +(define_insn "vec_interleave_highv2si_le" [(set (match_operand:V2SI 0 "register_operand" "=r") (vec_select:V2SI (vec_concat:V4SI (match_operand:V2SI 1 "reg_or_0_operand" "rO") (match_operand:V2SI 2 "reg_or_0_operand" "rO")) (parallel [(const_int 1) (const_int 3)])))] - "" + "!BYTES_BIG_ENDIAN" "v4int_h\t%0, %r2, %r1" [(set_attr "type" "X01")]) @@ -4550,11 +4724,14 @@ (match_operand:DI 2 "reg_or_0_operand" "")] "" { - /* Our instruction interleaves opposite of the way vec_interleave - works, so we need to reverse the source operands. */ + /* For little endian, our instruction interleaves opposite of the + way vec_interleave works, so we need to reverse the source + operands. */ + rtx opnd1 = BYTES_BIG_ENDIAN ? operands[1] : operands[2]; + rtx opnd2 = BYTES_BIG_ENDIAN ? operands[2] : operands[1]; tilegx_expand_builtin_vector_binop (gen_vec_interleave_highv2si, V2SImode, - operands[0], V2SImode, operands[2], - operands[1], true); + operands[0], V2SImode, opnd1, opnd2, + true); DONE; }) @@ -4562,13 +4739,38 @@ ;; {B1,B0} {A1,A0} ;; => {A1,A0,B1,B0} ;; => {A0,B0} -(define_insn "vec_interleave_lowv2si" +(define_expand "vec_interleave_lowv2si" + [(match_operand:V2SI 0 "register_operand" "") + (match_operand:V2SI 1 "reg_or_0_operand" "") + (match_operand:V2SI 2 "reg_or_0_operand" "")] + "" +{ + if (BYTES_BIG_ENDIAN) + emit_insn (gen_vec_interleave_lowv2si_be (operands[0], operands[1], + operands[2])); + else + emit_insn (gen_vec_interleave_lowv2si_le (operands[0], operands[1], + operands[2])); + DONE; +}) + +(define_insn "vec_interleave_lowv2si_be" + [(set (match_operand:V2SI 0 "register_operand" "=r") + (vec_select:V2SI + (vec_concat:V4SI (match_operand:V2SI 1 "reg_or_0_operand" "rO") + (match_operand:V2SI 2 "reg_or_0_operand" "rO")) + (parallel [(const_int 1) (const_int 3)])))] + "BYTES_BIG_ENDIAN" + "v4int_l\t%0, %r1, %r2" + [(set_attr "type" "X01")]) + +(define_insn "vec_interleave_lowv2si_le" [(set (match_operand:V2SI 0 "register_operand" "=r") (vec_select:V2SI (vec_concat:V4SI (match_operand:V2SI 1 "reg_or_0_operand" "rO") (match_operand:V2SI 2 "reg_or_0_operand" "rO")) (parallel [(const_int 0) (const_int 2)])))] - "" + "!BYTES_BIG_ENDIAN" "v4int_l\t%0, %r2, %r1" [(set_attr "type" "X01")]) @@ -4578,11 +4780,14 @@ (match_operand:DI 2 "reg_or_0_operand" "")] "" { - /* Our instruction interleaves opposite of the way vec_interleave - works, so we need to reverse the source operands. */ + /* For little endian, our instruction interleaves opposite of the + way vec_interleave works, so we need to reverse the source + operands. */ + rtx opnd1 = BYTES_BIG_ENDIAN ? operands[1] : operands[2]; + rtx opnd2 = BYTES_BIG_ENDIAN ? operands[2] : operands[1]; tilegx_expand_builtin_vector_binop (gen_vec_interleave_lowv2si, V2SImode, - operands[0], V2SImode, operands[2], - operands[1], true); + operands[0], V2SImode, opnd1, opnd2, + true); DONE; }) diff --git a/gcc/config/tilegx/tilegx.opt b/gcc/config/tilegx/tilegx.opt index a71f546..37c12fe 100644 --- a/gcc/config/tilegx/tilegx.opt +++ b/gcc/config/tilegx/tilegx.opt @@ -40,6 +40,14 @@ m64 Target Report RejectNegative Negative(m32) InverseMask(32BIT, 64BIT) Compile with 64 bit longs and pointers. +mbig-endian +Target Report RejectNegative Mask(BIG_ENDIAN) +Use big-endian byte order. + +mlittle-endian +Target Report RejectNegative InverseMask(BIG_ENDIAN) +Use little-endian byte order. + mcmodel= Target RejectNegative Joined Enum(cmodel) Var(tilegx_cmodel) Init(CM_SMALL) Use given TILE-Gx code model diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi index 7a61942..dc040cb 100644 --- a/gcc/doc/install.texi +++ b/gcc/doc/install.texi @@ -3188,6 +3188,8 @@ information have to. @item @uref{#tilegx-x-linux,,tilegx-*-linux*} @item +@uref{#tilegxbe-x-linux,,tilegxbe-*-linux*} +@item @uref{#tilepro-x-linux,,tilepro-*-linux*} @item @uref{#x-x-vxworks,,*-*-vxworks*} @@ -4480,8 +4482,16 @@ The C6X family of processors. This port requires binutils-2.22 or newer. @end html @anchor{tilegx-*-linux} @heading tilegx-*-linux* -The TILE-Gx processor running GNU/Linux. This port requires -binutils-2.22 or newer. +The TILE-Gx processor in little endian mode, running GNU/Linux. This +port requires binutils-2.22 or newer. + +@html +<hr /> +@end html +@anchor{tilegxbe-*-linux} +@heading tilegxbe-*-linux* +The TILE-Gx processor in big endian mode, running GNU/Linux. This +port requires binutils-2.23 or newer. @html <hr /> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 959664c..3d4812f 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -1012,7 +1012,8 @@ See RS/6000 and PowerPC Options. @gccoptlist{-Qy -Qn -YP,@var{paths} -Ym,@var{dir}} @emph{TILE-Gx Options} -@gccoptlist{-mcpu=@var{cpu} -m32 -m64 -mcmodel=@var{code-model}} +@gccoptlist{-mcpu=CPU -m32 -m64 -mbig-endian -mlittle-endian @gol +-mcmodel=@var{code-model}} @emph{TILEPro Options} @gccoptlist{-mcpu=@var{cpu} -m32} @@ -21344,6 +21345,12 @@ type is @samp{tilegx}. Generate code for a 32-bit or 64-bit environment. The 32-bit environment sets int, long, and pointer to 32 bits. The 64-bit environment sets int to 32 bits and long and pointer to 64 bits. + +@item -mbig-endian +@itemx -mlittle-endian +@opindex mbig-endian +@opindex mlittle-endian +Generate code in big/little endian mode, respectively. @end table @node TILEPro Options |