From patchwork Tue Aug 28 05:30:45 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Walter Lee X-Patchwork-Id: 180331 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 34CAA2C008D for ; Tue, 28 Aug 2012 15:31:40 +1000 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1346736702; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Date:Message-ID:From:To:Subject:Reply-To:MIME-Version: Content-Type:Mailing-List:Precedence:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:Sender:Delivered-To; bh=ESjaOpT C1CUtWIu77lowOWu/PGk=; b=Vd1Y3itY+ZC1mosK9CflUIs6qXTvSvXy3WbbkVa 8ILxX4ZbwikF99FGDY4rKw/e4qQ2eE2FWPVoVpi4hDSQsG5GnF3AHdlGrHGUEVoU AhXmYOM5C5n6fRCJV2QVj0Avh3MNwcIvaYgYisLrtla1Ww/uBRcFUlPFGKIt+hz4 C9k8= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:Received:Date:Message-ID:From:To:Subject:Reply-To:MIME-Version:Content-Type:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=edvX2ni4ruYiejqQqSeul6jYvrJTq6D+DlTA1MnmjQVPj9avfGuxTpc5e3cIJW 2NSJxnlKe7bvVF+S9aAXE41/buahnozA0F6uIKl+MYOzjsvrgZ88+XG6pF+DRcHw XzDWR6ZVGXF7xcXiEDGypQfyVrmpRIRGC1ELyuJwgGG2o=; Received: (qmail 10699 invoked by alias); 28 Aug 2012 05:31:24 -0000 Received: (qmail 10200 invoked by uid 22791); 28 Aug 2012 05:31:04 -0000 X-SWARE-Spam-Status: No, hits=-0.3 required=5.0 tests=AWL, BAYES_05, KAM_STOCKGEN, RP_MATCHES_RCVD, TW_EG X-Spam-Check-By: sourceware.org Received: from usmamail.tilera.com (HELO USMAMAIL.TILERA.COM) (12.216.194.151) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 28 Aug 2012 05:30:47 +0000 Received: from farm-0038.internal.tilera.com (10.2.0.68) by USMAEXCH2.tad.internal.tilera.com (10.3.0.33) with Microsoft SMTP Server (TLS) id 14.0.694.0; Tue, 28 Aug 2012 01:30:46 -0400 Received: (from walt@localhost) by farm-0038.internal.tilera.com (8.14.4/8.12.11/Submit) id q7S5UjYM009831; Tue, 28 Aug 2012 01:30:45 -0400 Date: Tue, 28 Aug 2012 01:30:45 -0400 Message-ID: <201208280530.q7S5UjYM009831@farm-0038.internal.tilera.com> From: Walter Lee To: Subject: [TILE-Gx, committed] support -mcmodel=MODEL Reply-To: Walter Lee MIME-Version: 1.0 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org This patch adds 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): 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. Index: gcc/doc/invoke.texi =================================================================== --- gcc/doc/invoke.texi (revision 190736) +++ gcc/doc/invoke.texi (working copy) @@ -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 Index: gcc/config/tilegx/tilegx.h =================================================================== --- gcc/config/tilegx/tilegx.h (revision 190736) +++ gcc/config/tilegx/tilegx.h (working copy) @@ -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 () Index: gcc/config/tilegx/predicates.md =================================================================== --- gcc/config/tilegx/predicates.md (revision 190736) +++ gcc/config/tilegx/predicates.md (working copy) @@ -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. Index: gcc/config/tilegx/tilegx.md =================================================================== --- gcc/config/tilegx/tilegx.md (revision 190736) +++ gcc/config/tilegx/tilegx.md (working copy) @@ -150,42 +150,43 @@ ;; Insns generating difference of two labels (UNSPEC_MOV_PCREL_STEP3 204) + (UNSPEC_MOV_LARGE_PCREL_STEP4 205) ;; Latency specifying loads. - (UNSPEC_LATENCY_L2 205) - (UNSPEC_LATENCY_MISS 206) + (UNSPEC_LATENCY_L2 206) + (UNSPEC_LATENCY_MISS 207) ;; A pseudo-op that prevents network operations from being ordered. - (UNSPEC_NETWORK_BARRIER 207) + (UNSPEC_NETWORK_BARRIER 208) ;; Operations that access network registers. - (UNSPEC_NETWORK_RECEIVE 208) - (UNSPEC_NETWORK_SEND 209) + (UNSPEC_NETWORK_RECEIVE 209) + (UNSPEC_NETWORK_SEND 210) ;; Stack protector operations - (UNSPEC_SP_SET 210) - (UNSPEC_SP_TEST 211) + (UNSPEC_SP_SET 211) + (UNSPEC_SP_TEST 212) ;; This is used to move a value to a SPR. - (UNSPEC_SPR_MOVE 212) + (UNSPEC_SPR_MOVE 213) ;; A call to __tls_get_addr - (UNSPEC_TLS_GD_CALL 213) + (UNSPEC_TLS_GD_CALL 214) ;; An opaque TLS "add" operation for TLS general dynamic model ;; access. - (UNSPEC_TLS_GD_ADD 214) + (UNSPEC_TLS_GD_ADD 215) ;; An opaque TLS "load" operation for TLS initial exec model access. - (UNSPEC_TLS_IE_LOAD 215) + (UNSPEC_TLS_IE_LOAD 216) ;; An opaque TLS "add" operation for TLS access. - (UNSPEC_TLS_ADD 216) + (UNSPEC_TLS_ADD 217) ;; Atomics - (UNSPEC_ATOMIC 217) - (UNSPEC_CMPXCHG 218) - (UNSPEC_XCHG 219) + (UNSPEC_ATOMIC 218) + (UNSPEC_CMPXCHG 219) + (UNSPEC_XCHG 220) ;; ;; The following are operands. @@ -199,24 +200,32 @@ (UNSPEC_HW2_LAST 306) (UNSPEC_HW0_PCREL 307) - (UNSPEC_HW1_LAST_PCREL 308) + (UNSPEC_HW1_PCREL 308) + (UNSPEC_HW1_LAST_PCREL 309) + (UNSPEC_HW2_LAST_PCREL 310) - (UNSPEC_HW0_GOT 309) - (UNSPEC_HW0_LAST_GOT 310) - (UNSPEC_HW1_LAST_GOT 311) + (UNSPEC_HW0_GOT 311) + (UNSPEC_HW0_LAST_GOT 312) + (UNSPEC_HW1_LAST_GOT 313) - (UNSPEC_HW0_TLS_GD 312) - (UNSPEC_HW1_LAST_TLS_GD 313) + (UNSPEC_HW0_TLS_GD 314) + (UNSPEC_HW1_LAST_TLS_GD 315) - (UNSPEC_HW0_TLS_IE 314) - (UNSPEC_HW1_LAST_TLS_IE 315) + (UNSPEC_HW0_TLS_IE 316) + (UNSPEC_HW1_LAST_TLS_IE 317) - (UNSPEC_HW0_TLS_LE 316) - (UNSPEC_HW1_LAST_TLS_LE 317) + (UNSPEC_HW0_TLS_LE 318) + (UNSPEC_HW1_LAST_TLS_LE 319) + + (UNSPEC_HW0_PLT_PCREL 320) + (UNSPEC_HW1_PLT_PCREL 321) + + (UNSPEC_HW1_LAST_PLT_PCREL 322) + (UNSPEC_HW2_LAST_PLT_PCREL 323) ;; This is used to wrap around the addresses of non-temporal load/store ;; intrinsics. - (UNSPEC_NON_TEMPORAL 318) + (UNSPEC_NON_TEMPORAL 324) ]) ;; Mark the last instruction of various latencies, used to @@ -885,15 +894,15 @@ ;; Addresses ;; -;; First step of the 3-insn sequence to materialize a symbolic -;; address. +;; The next three patterns are used to to materialize a position +;; independent address by adding the difference of two labels to a base +;; label in the text segment, assuming that the difference fits in 32 +;; signed bits. (define_expand "mov_address_step1" [(set (match_operand:DI 0 "register_operand" "") (const:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_HW2_LAST)))]) -;; Second step of the 3-insn sequence to materialize a symbolic -;; address. (define_expand "mov_address_step2" [(set (match_operand:DI 0 "register_operand" "") (unspec:DI @@ -902,8 +911,6 @@ UNSPEC_HW1))] UNSPEC_INSN_ADDR_SHL16INSLI))]) -;; Third step of the 3-insn sequence to materialize a symbolic -;; address. (define_expand "mov_address_step3" [(set (match_operand:DI 0 "register_operand" "") (unspec:DI @@ -988,6 +995,106 @@ "flag_pic" "add\t%0, %r1, %r2") +;; The next three patterns are used to to materialize a position +;; independent 64-bit address by adding the difference of two labels to +;; a base label in the text segment, without any limitation on the size +;; of the difference. +(define_expand "mov_large_pcrel_step1" + [(set (match_operand:DI 0 "register_operand" "") + (const:DI (unspec:DI + [(match_operand:DI 1 "symbolic_operand" "") + (match_operand:DI 2 "symbolic_operand" "")] + UNSPEC_HW2_LAST_PCREL)))] + "flag_pic") + +(define_expand "mov_large_pcrel_step2" + [(set (match_operand:DI 0 "register_operand" "") + (unspec:DI + [(match_operand:DI 1 "reg_or_0_operand" "") + (const:DI + (unspec:DI [(match_operand:DI 2 "symbolic_operand" "") + (match_operand:DI 3 "symbolic_operand" "")] + UNSPEC_HW1_PCREL))] + UNSPEC_INSN_ADDR_SHL16INSLI))] + "flag_pic") + +;; Note: step 3 is same as move_pcrel_step2. +(define_expand "mov_large_pcrel_step3" + [(set (match_operand:DI 0 "register_operand" "") + (unspec:DI + [(match_operand:DI 1 "reg_or_0_operand" "") + (const:DI + (unspec:DI [(match_operand:DI 2 "symbolic_operand" "") + (match_operand:DI 3 "symbolic_operand" "")] + UNSPEC_HW0_PCREL))] + UNSPEC_INSN_ADDR_SHL16INSLI))] + "flag_pic") + +(define_insn "mov_large_pcrel_step4" + [(set (match_operand:DI 0 "register_operand" "=r") + (unspec:DI [(match_operand:DI 1 "reg_or_0_operand" "rO") + (match_operand:DI 2 "reg_or_0_operand" "rO") + (match_operand:DI 3 "symbolic_operand" "in") + (match_operand:DI 4 "symbolic_operand" "in")] + UNSPEC_MOV_LARGE_PCREL_STEP4))] + "flag_pic" + "add\t%0, %r1, %r2") + +;; The next three patterns are used to materialize a position +;; independent 64-bit plt address by adding the difference of two +;; labels to a base label in the text segment. +(define_expand "mov_plt_pcrel_step1" + [(set (match_operand:DI 0 "register_operand" "") + (const:DI (unspec:DI + [(match_operand:DI 1 "symbolic_operand" "") + (match_operand:DI 2 "symbolic_operand" "")] + UNSPEC_HW2_LAST_PLT_PCREL)))] + "flag_pic") + +(define_expand "mov_plt_pcrel_step2" + [(set (match_operand:DI 0 "register_operand" "") + (unspec:DI + [(match_operand:DI 1 "reg_or_0_operand" "") + (const:DI + (unspec:DI [(match_operand:DI 2 "symbolic_operand" "") + (match_operand:DI 3 "symbolic_operand" "")] + UNSPEC_HW1_PLT_PCREL))] + UNSPEC_INSN_ADDR_SHL16INSLI))] + "flag_pic") + +(define_expand "mov_plt_pcrel_step3" + [(set (match_operand:DI 0 "register_operand" "") + (unspec:DI + [(match_operand:DI 1 "reg_or_0_operand" "") + (const:DI + (unspec:DI [(match_operand:DI 2 "symbolic_operand" "") + (match_operand:DI 3 "symbolic_operand" "")] + UNSPEC_HW0_PLT_PCREL))] + UNSPEC_INSN_ADDR_SHL16INSLI))] + "flag_pic") + +;; The next two patterns are used to materialize a position independent +;; 32-bit plt address by adding the difference of two labels to a base +;; label in the text segment. +(define_expand "mov_plt_pcrel_step1_32bit" + [(set (match_operand:SI 0 "register_operand" "") + (const:SI (unspec:SI + [(match_operand:SI 1 "symbolic_operand" "") + (match_operand:SI 2 "symbolic_operand" "")] + UNSPEC_HW1_LAST_PLT_PCREL)))] + "flag_pic") + +(define_expand "mov_plt_pcrel_step2_32bit" + [(set (match_operand:SI 0 "register_operand" "") + (unspec:SI + [(match_operand:SI 1 "reg_or_0_operand" "") + (const:SI + (unspec:SI [(match_operand:SI 2 "symbolic_operand" "") + (match_operand:SI 3 "symbolic_operand" "")] + UNSPEC_HW0_PLT_PCREL))] + UNSPEC_INSN_ADDR_SHL16INSLI))] + "flag_pic") + (define_expand "add_got16" [(set (match_operand:I48MODE 0 "register_operand" "") (plus:I48MODE @@ -2300,7 +2407,29 @@ (use (reg:DI 54)) (clobber (reg:DI 55))])] "" - "") +{ + rtx orig_addr = XEXP (operands[0], 0); + rtx addr; + if (GET_CODE (orig_addr) == SYMBOL_REF) + { + if (tilegx_cmodel == CM_LARGE) + { + addr = gen_reg_rtx (Pmode); + tilegx_expand_set_const64 (addr, orig_addr); + operands[0] = gen_rtx_MEM (DImode, addr); + } + else if (tilegx_cmodel == CM_LARGE_PIC) + { + crtl->uses_pic_offset_table = 1; + addr = gen_reg_rtx (Pmode); + if (SYMBOL_REF_LOCAL_P (orig_addr)) + tilegx_compute_pcrel_address (addr, orig_addr); + else + tilegx_compute_pcrel_plt_address (addr, orig_addr); + operands[0] = gen_rtx_MEM (DImode, addr); + } + } +}) (define_insn "*call_insn" [(call (mem:DI (match_operand:I48MODE 0 "call_address_operand" "rO,i")) @@ -2319,7 +2448,30 @@ (match_operand 2 "" ""))) (use (reg:DI 54)) (clobber (reg:DI 55))])] - "") + "" +{ + rtx orig_addr = XEXP (operands[1], 0); + rtx addr; + if (GET_CODE (orig_addr) == SYMBOL_REF) + { + if (tilegx_cmodel == CM_LARGE) + { + addr = gen_reg_rtx (Pmode); + tilegx_expand_set_const64 (addr, orig_addr); + operands[1] = gen_rtx_MEM (DImode, addr); + } + else if (tilegx_cmodel == CM_LARGE_PIC) + { + crtl->uses_pic_offset_table = 1; + addr = gen_reg_rtx (Pmode); + if (SYMBOL_REF_LOCAL_P (orig_addr)) + tilegx_compute_pcrel_address (addr, orig_addr); + else + tilegx_compute_pcrel_plt_address (addr, orig_addr); + operands[1] = gen_rtx_MEM (DImode, addr); + } + } +}) (define_insn "*call_value_insn" [(set (match_operand 0 "register_operand" "=r,r") Index: gcc/config/tilegx/tilegx.opt =================================================================== --- gcc/config/tilegx/tilegx.opt (revision 190736) +++ gcc/config/tilegx/tilegx.opt (working copy) @@ -19,6 +19,9 @@ ; along with GCC; see the file COPYING3. If not see ; . +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) Index: gcc/config/tilegx/tilegx-opts.h =================================================================== --- gcc/config/tilegx/tilegx-opts.h (revision 0) +++ gcc/config/tilegx/tilegx-opts.h (revision 0) @@ -0,0 +1,34 @@ +/* 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 + . */ + +#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 Index: gcc/config/tilegx/tilegx-protos.h =================================================================== --- gcc/config/tilegx/tilegx-protos.h (revision 190736) +++ gcc/config/tilegx/tilegx-protos.h (working copy) @@ -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); Index: gcc/config/tilegx/tilegx.c =================================================================== --- gcc/config/tilegx/tilegx.c (revision 190736) +++ gcc/config/tilegx/tilegx.c (working copy) @@ -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 mach 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 a 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 a } +/* 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 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 op 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, 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, 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, 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, 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);