Commit 1773cd77 by Walter Lee Committed by Walter Lee

Add support for the -mcmodel=MODEL flag on TILE-Gx.

Add support for the -mcmodel=MODEL flag on TILE-Gx.  The models
supported are small and large.  In the small model (default), distance
for direct calls is limited to 500M in either direction.  PC-relative
addresses are 32 bits.  Absolute addresses support the full address
range.  In the large model, there is no limiation on call distance,
pc-relative addresses, or absolute addresses.
	* doc/invoke.texi: Document -mcmodel=small, -mcmodel=large.
	* config/tilegx/tilegx.h: Include config/tilegx/tilegx-opts.h.
	(CRT_CALL_STATIC_FUNCTION): Define.
	* config/tilegx/predicates.md (const_last_symbolic_operand):
	Handle UNSPEC_HW2_LAST_PCREL, UNSPEC_HW1_LAST_PLT_PCREL, and
	UNSPEC_HW2_LAST_PLT_PCREL.
	(const_symbolic_operand): Handle UNSPEC_HW1_PCREL,
	UNSPEC_HW0_PLT_PCREL, and UNSPEC_HW1_PLT_PCREL.
	* config/tilegx/tilegx.md (UNSPEC_MOV_LARGE_PCREL_STEP4): Define,
	and renumber the constants that follow.
	(UNSPEC_HW1_PCREL): Define, and renumber the constants that
	follow.
	(UNSPEC_HW0_PLT_PCREL): Define.
	(UNSPEC_HW1_PLT_PCREL): Define.
	(UNSPEC_HW1_LAST_PLT_PCREL): Define.
	(UNSPEC_HW2_LAST_PLT_PCREL): Define.
	(mov_large_pcrel_step1): Define.
	(mov_large_pcrel_step2): Define.
	(mov_large_pcrel_step3): Define.
	(mov_large_pcrel_step4): Define.
	(mov_plt_pcrel_step1): Define.
	(mov_plt_pcrel_step2): Define.
	(mov_plt_pcrel_step3): Define.
	(mov_plt_pcrel_step1_32bit): Define.
	(mov_plt_pcrel_step2_32bit): Define.
	(call): Handle tilegx_cmodel == CM_LARGE, CM_LARGE_PIC.
	(call_value): Ditto.
	* config/tilegx/tilegx.opt: Include config/tilegx/tilegx-opts.h.
	(mcmodel): New option.
	(enum cmodel): Define.
	(CM_SMALL): Define.
	(CM_LARGE): Define.
	* config/tilegx/tilegx-protos.h (tilegx_compute_pcrel_address):
	Declare.
	(tilegx_compute_pcrel_plt_address): Declare.
	* config/tilegx/tilegx.c (tilegx_option_override): Handle
	tilegx_cmodel.
	(tilegx_function_ok_for_sibcall): Ditto.
	(compute_pcrel_address): Rename to tilegx_compute_pcrel_address,
	and don't declare static.  Handle tilegx_cmodel.
	(tilegx_compute_pcrel_plt_address): Define.
	(tilegx_legitimize_pic_address): Rename calls to
	compute_pcrel_address.
	(tilegx_delegitimize_address): Handle UNSPEC_HW1_PCREL,
	UNSPEC_HW2_LAST_PCREL, UNSPEC_HW0_PLT_PCREL, UNSPEC_HW1_PLT_PCREL,
	UNSPEC_HW1_LAST_PLT_PCREL, UNSPEC_HW2_LAST_PLT_PCREL.
	(load_pic_register): Rename call to compute_pcrel_address.
	(tilegx_print_operand): Handle UNSPEC_HW1_PCREL,
	UNSPEC_HW2_LAST_PCREL, UNSPEC_HW0_PLT_PCREL, UNSPEC_HW1_PLT_PCREL,
	UNSPEC_HW1_LAST_PLT_PCREL, UNSPEC_HW2_LAST_PLT_PCREL.

From-SVN: r190737
parent bebfb71b
2012-08-28 Walter Lee <walt@tilera.com>
* doc/invoke.texi: Document -mcmodel=small, -mcmodel=large.
* config/tilegx/tilegx.h: Include config/tilegx/tilegx-opts.h.
(CRT_CALL_STATIC_FUNCTION): Define.
* config/tilegx/predicates.md (const_last_symbolic_operand):
Handle UNSPEC_HW2_LAST_PCREL, UNSPEC_HW1_LAST_PLT_PCREL, and
UNSPEC_HW2_LAST_PLT_PCREL.
(const_symbolic_operand): Handle UNSPEC_HW1_PCREL,
UNSPEC_HW0_PLT_PCREL, and UNSPEC_HW1_PLT_PCREL.
* config/tilegx/tilegx.md (UNSPEC_MOV_LARGE_PCREL_STEP4): Define,
and renumber the constants that follow.
(UNSPEC_HW1_PCREL): Ditto.
(UNSPEC_HW2_LAST_PCREL): Ditto.
(UNSPEC_HW0_PLT_PCREL): Define.
(UNSPEC_HW1_PLT_PCREL): Define.
(UNSPEC_HW1_LAST_PLT_PCREL): Define.
(UNSPEC_HW2_LAST_PLT_PCREL): Define.
(mov_large_pcrel_step1): Define.
(mov_large_pcrel_step2): Define.
(mov_large_pcrel_step3): Define.
(mov_large_pcrel_step4): Define.
(mov_plt_pcrel_step1): Define.
(mov_plt_pcrel_step2): Define.
(mov_plt_pcrel_step3): Define.
(mov_plt_pcrel_step1_32bit): Define.
(mov_plt_pcrel_step2_32bit): Define.
(call): Handle tilegx_cmodel == CM_LARGE, CM_LARGE_PIC.
(call_value): Ditto.
* config/tilegx/tilegx.opt: Include config/tilegx/tilegx-opts.h.
(mcmodel): New option.
(enum cmodel): Define.
(CM_SMALL): Define.
(CM_LARGE): Define.
* config/tilegx/tilegx-opts.h: New file.
* config/tilegx/tilegx-protos.h (tilegx_compute_pcrel_address):
Declare.
(tilegx_compute_pcrel_plt_address): Declare.
* config/tilegx/tilegx.c (tilegx_option_override): Handle
tilegx_cmodel.
(tilegx_function_ok_for_sibcall): Ditto.
(compute_pcrel_address): Rename to tilegx_compute_pcrel_address,
and don't declare static. Handle tilegx_cmodel.
(tilegx_compute_pcrel_plt_address): Define.
(tilegx_legitimize_pic_address): Rename calls to
compute_pcrel_address.
(tilegx_delegitimize_address): Handle UNSPEC_HW1_PCREL,
UNSPEC_HW2_LAST_PCREL, UNSPEC_HW0_PLT_PCREL, UNSPEC_HW1_PLT_PCREL,
UNSPEC_HW1_LAST_PLT_PCREL, UNSPEC_HW2_LAST_PLT_PCREL.
(load_pic_register): Rename call to compute_pcrel_address.
(tilegx_print_operand): Handle UNSPEC_HW1_PCREL,
UNSPEC_HW2_LAST_PCREL, UNSPEC_HW0_PLT_PCREL, UNSPEC_HW1_PLT_PCREL,
UNSPEC_HW1_LAST_PLT_PCREL, UNSPEC_HW2_LAST_PLT_PCREL.
2012-08-27 Maxim Kuvyrkov <maxim@codesourcery.com>
* sched-deps.c (add_dependence_list_and_free): Simplify.
......
......@@ -80,11 +80,14 @@
(match_test "XINT (XEXP (op,0), 1) == UNSPEC_HW1_LAST")
(match_test "XINT (XEXP (op,0), 1) == UNSPEC_HW2_LAST")
(match_test "XINT (XEXP (op,0), 1) == UNSPEC_HW1_LAST_PCREL")
(match_test "XINT (XEXP (op,0), 1) == UNSPEC_HW2_LAST_PCREL")
(match_test "XINT (XEXP (op,0), 1) == UNSPEC_HW0_LAST_GOT")
(match_test "XINT (XEXP (op,0), 1) == UNSPEC_HW1_LAST_GOT")
(match_test "XINT (XEXP (op,0), 1) == UNSPEC_HW1_LAST_TLS_GD")
(match_test "XINT (XEXP (op,0), 1) == UNSPEC_HW1_LAST_TLS_IE")
(match_test "XINT (XEXP (op,0), 1) == UNSPEC_HW1_LAST_TLS_LE"))))
(match_test "XINT (XEXP (op,0), 1) == UNSPEC_HW1_LAST_TLS_LE")
(match_test "XINT (XEXP (op,0), 1) == UNSPEC_HW1_LAST_PLT_PCREL")
(match_test "XINT (XEXP (op,0), 1) == UNSPEC_HW2_LAST_PLT_PCREL"))))
;; Returns 1 if OP is an unspec wrapper for a symbol, got, or tls
;; reference.
......@@ -96,10 +99,13 @@
(match_test "XINT (XEXP (op,0), 1) == UNSPEC_HW2")
(match_test "XINT (XEXP (op,0), 1) == UNSPEC_HW3")
(match_test "XINT (XEXP (op,0), 1) == UNSPEC_HW0_PCREL")
(match_test "XINT (XEXP (op,0), 1) == UNSPEC_HW1_PCREL")
(match_test "XINT (XEXP (op,0), 1) == UNSPEC_HW0_GOT")
(match_test "XINT (XEXP (op,0), 1) == UNSPEC_HW0_TLS_GD")
(match_test "XINT (XEXP (op,0), 1) == UNSPEC_HW0_TLS_IE")
(match_test "XINT (XEXP (op,0), 1) == UNSPEC_HW0_TLS_LE"))))
(match_test "XINT (XEXP (op,0), 1) == UNSPEC_HW0_TLS_LE")
(match_test "XINT (XEXP (op,0), 1) == UNSPEC_HW0_PLT_PCREL")
(match_test "XINT (XEXP (op,0), 1) == UNSPEC_HW1_PLT_PCREL"))))
;; Return 1 if OP is a 8-element vector constant with identical signed
;; 8-bit elements or any register.
......
/* Definitions for option handling for TILE-Gx.
Copyright (C) 2012
Free Software Foundation, Inc.
Contributed by Walter Lee (walt@tilera.com)
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published
by the Free Software Foundation; either version 3, or (at your
option) any later version.
GCC is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef TILEGX_OPTS_H
#define TILEGX_OPTS_H
enum cmodel {
CM_SMALL, /* Makes various assumpation about sizes of code and
data fits. */
CM_LARGE, /* No assumptions. */
CM_SMALL_PIC, /* Makes various assumpation about sizes of code and
data fits. */
CM_LARGE_PIC /* No assumptions. */
};
#endif
......@@ -23,6 +23,8 @@
#define GCC_TILEGX_PROTOS_H
extern void tilegx_init_expanders (void);
extern void tilegx_compute_pcrel_address (rtx, rtx);
extern void tilegx_compute_pcrel_plt_address (rtx, rtx);
extern bool tilegx_legitimate_pic_operand_p (rtx);
extern rtx tilegx_simd_int (rtx, enum machine_mode);
......
......@@ -67,6 +67,29 @@ static bool output_memory_autoinc_first;
static void
tilegx_option_override (void)
{
if (global_options_set.x_tilegx_cmodel)
{
switch (tilegx_cmodel)
{
case CM_SMALL:
case CM_SMALL_PIC:
if (flag_pic)
tilegx_cmodel = CM_SMALL_PIC;
break;
case CM_LARGE:
case CM_LARGE_PIC:
if (flag_pic)
tilegx_cmodel = CM_LARGE_PIC;
break;
default:
gcc_unreachable ();
}
}
else
tilegx_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;
/* When modulo scheduling is enabled, we still rely on regular
scheduler for bundling. */
if (flag_modulo_sched)
......@@ -119,7 +142,8 @@ tilegx_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED,
static bool
tilegx_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
{
return decl != NULL;
return (tilegx_cmodel != CM_LARGE && tilegx_cmodel != CM_LARGE_PIC
&& (decl != NULL));
}
......@@ -1024,12 +1048,12 @@ tilegx_legitimize_tls_address (rtx addr)
/* Returns a register that points to ADDR, a symbolic address, by
computing its address relative to tilegx_text_label_symbol. */
static void
compute_pcrel_address (rtx result, rtx addr)
void
tilegx_compute_pcrel_address (rtx result, rtx addr)
{
rtx text_label_symbol = tilegx_text_label_symbol ();
rtx text_label_rtx = tilegx_text_label_rtx ();
rtx temp, temp2;
rtx temp, temp2, temp3;
temp = create_temp_reg_if_possible (Pmode, result);
temp2 = create_temp_reg_if_possible (Pmode, result);
......@@ -1043,6 +1067,18 @@ compute_pcrel_address (rtx result, rtx addr)
text_label_rtx,
addr, text_label_symbol));
}
else if (tilegx_cmodel == CM_LARGE_PIC)
{
temp3 = create_temp_reg_if_possible (Pmode, result);
emit_insn (gen_mov_large_pcrel_step1 (temp, addr, text_label_symbol));
emit_insn (gen_mov_large_pcrel_step2 (temp2, temp, addr,
text_label_symbol));
emit_insn (gen_mov_large_pcrel_step3 (temp3, temp2, addr,
text_label_symbol));
emit_insn (gen_mov_large_pcrel_step4 (result, temp3,
text_label_rtx,
addr, text_label_symbol));
}
else
{
emit_insn (gen_mov_pcrel_step1 (temp, addr, text_label_symbol));
......@@ -1054,6 +1090,41 @@ compute_pcrel_address (rtx result, rtx addr)
}
/* Returns a register that points to the plt entry of ADDR, a symbolic
address, by computing its address relative to
tilegx_text_label_symbol. */
void
tilegx_compute_pcrel_plt_address (rtx result, rtx addr)
{
rtx text_label_symbol = tilegx_text_label_symbol ();
rtx text_label_rtx = tilegx_text_label_rtx ();
rtx temp, temp2, temp3;
temp = create_temp_reg_if_possible (Pmode, result);
temp2 = create_temp_reg_if_possible (Pmode, result);
if (TARGET_32BIT)
{
emit_insn (gen_mov_plt_pcrel_step1_32bit (temp, addr,
text_label_symbol));
emit_insn (gen_mov_plt_pcrel_step2_32bit (temp2, temp, addr,
text_label_symbol));
emit_move_insn (result, gen_rtx_PLUS (Pmode, temp2, text_label_rtx));
}
else
{
temp3 = create_temp_reg_if_possible (Pmode, result);
emit_insn (gen_mov_plt_pcrel_step1 (temp, addr, text_label_symbol));
emit_insn (gen_mov_plt_pcrel_step2 (temp2, temp, addr,
text_label_symbol));
emit_insn (gen_mov_plt_pcrel_step3 (temp3, temp2, addr,
text_label_symbol));
emit_move_insn (result, gen_rtx_PLUS (Pmode, temp3, text_label_rtx));
}
}
/* Legitimize PIC addresses. If the address is already
position-independent, we return ORIG. Newly generated
position-independent addresses go into a reg. This is REG if
......@@ -1079,7 +1150,7 @@ tilegx_legitimize_pic_address (rtx orig,
loading in the address, so that these instructions can be
optimized properly. */
rtx temp_reg = create_temp_reg_if_possible (Pmode, reg);
compute_pcrel_address (temp_reg, orig);
tilegx_compute_pcrel_address (temp_reg, orig);
/* Note: this is conservative. We use the text_label but we
don't use the pic_offset_table. However, in some cases
......@@ -1196,7 +1267,7 @@ tilegx_legitimize_pic_address (rtx orig,
loading in the address, so that these instructions can be
optimized properly. */
temp_reg = create_temp_reg_if_possible (Pmode, reg);
compute_pcrel_address (temp_reg, orig);
tilegx_compute_pcrel_address (temp_reg, orig);
/* Note: this is conservative. We use the text_label but we
don't use the pic_offset_table. */
......@@ -1250,7 +1321,13 @@ tilegx_delegitimize_address (rtx x)
case UNSPEC_HW1_LAST:
case UNSPEC_HW2_LAST:
case UNSPEC_HW0_PCREL:
case UNSPEC_HW1_PCREL:
case UNSPEC_HW1_LAST_PCREL:
case UNSPEC_HW2_LAST_PCREL:
case UNSPEC_HW0_PLT_PCREL:
case UNSPEC_HW1_PLT_PCREL:
case UNSPEC_HW1_LAST_PLT_PCREL:
case UNSPEC_HW2_LAST_PLT_PCREL:
case UNSPEC_HW0_GOT:
case UNSPEC_HW0_LAST_GOT:
case UNSPEC_HW1_LAST_GOT:
......@@ -1290,7 +1367,7 @@ load_pic_register (bool delay_pic_helper ATTRIBUTE_UNUSED)
emit_insn (gen_insn_lnk_and_label (text_label_rtx, text_label_symbol));
}
compute_pcrel_address (tilegx_got_rtx (), got_symbol);
tilegx_compute_pcrel_address (tilegx_got_rtx (), got_symbol);
flag_pic = orig_flag_pic;
......@@ -2577,7 +2654,7 @@ tilegx_expand_tablejump (rtx op0, rtx op1)
rtx temp = gen_reg_rtx (Pmode);
rtx temp2 = gen_reg_rtx (Pmode);
compute_pcrel_address (temp, gen_rtx_LABEL_REF (Pmode, op1));
tilegx_compute_pcrel_address (temp, gen_rtx_LABEL_REF (Pmode, op1));
emit_move_insn (temp2,
gen_rtx_PLUS (Pmode,
convert_to_mode (Pmode, op0, false),
......@@ -4961,6 +5038,7 @@ tilegx_print_operand (FILE *file, rtx x, int code)
opstr = "hw0";
break;
case UNSPEC_HW1:
case UNSPEC_HW1_PCREL:
opstr = "hw1";
break;
case UNSPEC_HW2:
......@@ -4977,6 +5055,7 @@ tilegx_print_operand (FILE *file, rtx x, int code)
opstr = "hw1_last";
break;
case UNSPEC_HW2_LAST:
case UNSPEC_HW2_LAST_PCREL:
opstr = "hw2_last";
break;
case UNSPEC_HW0_GOT:
......@@ -5006,6 +5085,18 @@ tilegx_print_operand (FILE *file, rtx x, int code)
case UNSPEC_HW1_LAST_TLS_LE:
opstr = "hw1_last_tls_le";
break;
case UNSPEC_HW0_PLT_PCREL:
opstr = "hw0_plt";
break;
case UNSPEC_HW1_PLT_PCREL:
opstr = "hw1_plt";
break;
case UNSPEC_HW1_LAST_PLT_PCREL:
opstr = "hw1_last_plt";
break;
case UNSPEC_HW2_LAST_PLT_PCREL:
opstr = "hw2_last_plt";
break;
default:
output_operand_lossage ("invalid %%H specifier");
}
......@@ -5015,7 +5106,13 @@ tilegx_print_operand (FILE *file, rtx x, int code)
output_addr_const (file, addr);
if (unspec == UNSPEC_HW0_PCREL
|| unspec == UNSPEC_HW1_LAST_PCREL)
|| unspec == UNSPEC_HW1_PCREL
|| unspec == UNSPEC_HW1_LAST_PCREL
|| unspec == UNSPEC_HW2_LAST_PCREL
|| unspec == UNSPEC_HW0_PLT_PCREL
|| unspec == UNSPEC_HW1_PLT_PCREL
|| unspec == UNSPEC_HW1_LAST_PLT_PCREL
|| unspec == UNSPEC_HW2_LAST_PLT_PCREL)
{
rtx addr2 = XVECEXP (XEXP (x, 0), 0, 1);
fputs (" - " , file);
......
......@@ -31,6 +31,8 @@
} \
while (0)
#include "config/tilegx/tilegx-opts.h"
/* Target CPU builtins. */
#define TARGET_CPU_CPP_BUILTINS() \
......@@ -480,6 +482,19 @@ enum reg_class
assemble_name ((FILE), (NAME)), \
fprintf ((FILE), ",%u\n", (unsigned int)(ROUNDED)))
#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
static void __attribute__((__used__)) \
call_ ## FUNC (void) \
{ \
asm (SECTION_OP); \
asm ("{ moveli r0, hw2_last(" #FUNC " - . - 8); lnk r1 }\n"); \
asm ("shl16insli r0, r0, hw1(" #FUNC " - .)\n"); \
asm ("shl16insli r0, r0, hw0(" #FUNC " - . + 8)\n"); \
asm ("add r0, r1, r0\n"); \
asm ("jalr r0\n"); \
asm (TEXT_SECTION_ASM_OP); \
}
#define INIT_EXPANDERS tilegx_init_expanders ()
......
......@@ -19,6 +19,9 @@
; along with GCC; see the file COPYING3. If not see
; <http://www.gnu.org/licenses/>.
HeaderInclude
config/tilegx/tilegx-opts.h
mcpu=
Target RejectNegative Joined Enum(tilegx_cpu) Var(tilegx_cpu) Init(0)
-mcpu=CPU Use features of and schedule code for given CPU
......@@ -38,3 +41,16 @@ m64
Target Report RejectNegative Negative(m32) InverseMask(32BIT, 64BIT)
Compile with 64 bit longs and pointers.
mcmodel=
Target RejectNegative Joined Enum(cmodel) Var(tilegx_cmodel) Init(CM_SMALL)
Use given TILE-Gx code model
Enum
Name(cmodel) Type(enum cmodel)
Known code models (for use with the -mcmodel= option):
EnumValue
Enum(cmodel) String(small) Value(CM_SMALL)
EnumValue
Enum(cmodel) String(large) Value(CM_LARGE)
......@@ -929,7 +929,7 @@ See RS/6000 and PowerPC Options.
@gccoptlist{-Qy -Qn -YP,@var{paths} -Ym,@var{dir}}
@emph{TILE-Gx Options}
@gccoptlist{-mcpu=CPU -m32 -m64}
@gccoptlist{-mcpu=CPU -m32 -m64 -mcmodel=@var{code-model}}
@emph{TILEPro Options}
@gccoptlist{-mcpu=CPU -m32}
......@@ -18937,6 +18937,17 @@ The assembler uses this option.
These @samp{-m} options are supported on the TILE-Gx:
@table @gcctabopt
@item -mcmodel=small
@opindex mcmodel=small
Generate code for the small model. Distance for direct calls is
limited to 500M in either direction. PC-relative addresses are 32
bits. Absolute addresses support the full address range.
@item -mcmodel=large
@opindex mcmodel=large
Generate code for the large model. There is no limiation on call
distance, pc-relative addresses, or absolute addresses.
@item -mcpu=@var{name}
@opindex mcpu
Selects the type of CPU to be targeted. Currently the only supported
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment