From patchwork Tue Feb 22 00:23:09 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Daney X-Patchwork-Id: 83901 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 5CED5B716A for ; Tue, 22 Feb 2011 11:23:28 +1100 (EST) Received: (qmail 11630 invoked by alias); 22 Feb 2011 00:23:24 -0000 Received: (qmail 11620 invoked by uid 22791); 22 Feb 2011 00:23:21 -0000 X-SWARE-Spam-Status: No, hits=0.2 required=5.0 tests=AWL, BAYES_50, KAM_STOCKGEN, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail3.caviumnetworks.com (HELO mail3.caviumnetworks.com) (12.108.191.235) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 22 Feb 2011 00:23:16 +0000 Received: from caexch01.caveonetworks.com (Not Verified[192.168.16.9]) by mail3.caviumnetworks.com with MailMarshal (v6,7,2,8378) id ; Mon, 21 Feb 2011 16:24:07 -0800 Received: from caexch01.caveonetworks.com ([192.168.16.9]) by caexch01.caveonetworks.com with Microsoft SMTPSVC(6.0.3790.4675); Mon, 21 Feb 2011 16:23:14 -0800 Received: from dd1.caveonetworks.com ([12.108.191.236]) by caexch01.caveonetworks.com over TLS secured channel with Microsoft SMTPSVC(6.0.3790.4675); Mon, 21 Feb 2011 16:23:14 -0800 Message-ID: <4D6301ED.7040509@caviumnetworks.com> Date: Mon, 21 Feb 2011 16:23:09 -0800 From: David Daney User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.15) Gecko/20101027 Fedora/3.0.10-1.fc12 Thunderbird/3.0.10 MIME-Version: 1.0 To: rdsandiford@googlemail.com, GCC Patches , "Pinski, Andrew" Subject: Re: RFC: A new MIPS64 ABI References: <4D5990A4.2050308__41923.1521235362$1297715435$gmane$org@caviumnetworks.com> <87hbbxqihm.fsf@firetop.home> In-Reply-To: <87hbbxqihm.fsf@firetop.home> X-IsSubscribed: yes 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 CC list trimmed, and redirected to gcc-patches@ On 02/21/2011 11:45 AM, Richard Sandiford wrote: > David Daney writes: >> Background: >> >> Current MIPS 32-bit ABIs (both o32 and n32) are restricted to 2GB of >> user virtual memory space. This is due the way MIPS32 memory space is >> segmented. Only the range from 0..2^31-1 is available. Pointer >> values are always sign extended. >> >> Because there are not already enough MIPS ABIs, I present the ... >> >> Proposal: A new ABI to support 4GB of address space with 32-bit >> pointers. > > FWIW, I'd be happy to see this go into GCC. > Ok, here is the general idea: Everything identical to n32, except Pmode == DImode and POINTERS_EXTEND_UNSIGNED == true. Here is a patch that allows me to generate plausible looking assembly for trivial programs. Modulo lines that are too long and other possible coding standard violations, what do you think about this approach. Notes: o Only works for TARGET_EXPLICIT_RELOCS, but this could change with assembler support I suppose. o -mno-shared doesn't improve code over -mshared -------------8<------------ int foo; void f(void); int *bar(void) { f(); return &foo; } struct dd { int a; void *b; }; void *baa(struct dd *i) { return i->b; } -------------8<------------ Yields: .file 1 "n32test.c" .section .mdebug.abiNB32 .previous .gnu_attribute 4, 1 .abicalls .text .align 2 .align 3 .globl bar .set nomips16 .ent bar .type bar, @function bar: .frame $sp,16,$31 # vars= 0, regs= 2/0, args= 0, gp= 0 .mask 0x90000000,-8 .fmask 0x00000000,0 .set noreorder .set nomacro daddiu $sp,$sp,-16 sd $28,0($sp) ori $28,$0,%hi(__gnu_local_gp) dsll $28,$28,16 daddiu $28,$28,%lo(__gnu_local_gp) lwu $25,%call16(f)($28) sd $31,8($sp) .reloc 1f,R_MIPS_JALR,f 1: jalr $25 nop ld $31,8($sp) lwu $2,%got_disp(foo)($28) ld $28,0($sp) j $31 daddiu $sp,$sp,16 .set macro .set reorder .end bar .size bar, .-bar .align 2 .align 3 .globl baa .set nomips16 .ent baa .type baa, @function baa: .frame $sp,0,$31 # vars= 0, regs= 0/0, args= 0, gp= 0 .mask 0x00000000,0 .fmask 0x00000000,0 .set noreorder .set nomacro j $31 lwu $2,4($4) .set macro .set reorder .end baa .size baa, .-baa .comm foo,4,4 .ident "GCC: (GNU) 4.6.0 20110218 (experimental) [trunk revision 170267]" Index: gcc/config/mips/mips.md =================================================================== --- gcc/config/mips/mips.md (revision 170267) +++ gcc/config/mips/mips.md (working copy) @@ -97,6 +97,8 @@ (define_c_enum "unspec" [ UNSPEC_UPDATE_GOT_VERSION ;; Symbolic accesses. + UNSPEC_LA_EXTEND + UNSPEC_LA_EXTEND_LO UNSPEC_LOAD_CALL UNSPEC_LOAD_GOT UNSPEC_TLS_LDM @@ -2813,8 +2815,33 @@ (define_insn "*_trunc_exts" (define_expand "zero_extendsidi2" [(set (match_operand:DI 0 "register_operand") - (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand")))] - "TARGET_64BIT") + (zero_extend:DI (match_operand:SI 1 "general_operand")))] + "TARGET_64BIT" +{ + if (immediate_operand (operands[1], SImode)) + { + mips_expand_zero_extend_symbol (operands[0], operands[1]); + DONE; + } +}) + +(define_insn "zero_extendsidi_high_address" + [(set (match_operand:DI 0 "register_operand" "=d") + (unspec:DI [(zero_extend:DI (match_operand:SI 1 "immediate_operand" "i"))] UNSPEC_LA_EXTEND))] + "TARGET_64BIT" + "ori\t%0,%.,%h1" + [(set_attr "move_type" "const") + (set_attr "mode" "DI")]) + +(define_insn "zero_extendsidi_low_address" + [(set (match_operand:DI 0 "register_operand" "=d") + (unspec:DI [(lo_sum:DI + (match_operand:DI 1 "register_operand" "d") + (match_operand:SI 2 "immediate_operand" "i"))] UNSPEC_LA_EXTEND_LO))] + "TARGET_64BIT" + "daddiu\t%0,%1,%R2" + [(set_attr "move_type" "const") + (set_attr "mode" "DI")]) (define_insn_and_split "*zero_extendsidi2" [(set (match_operand:DI 0 "register_operand" "=d,d") @@ -3868,7 +3895,10 @@ (define_insn "load_got" (match_operand:P 2 "immediate_operand" "")] UNSPEC_LOAD_GOT))] "" - "\t%0,%R2(%1)" + {if (TARGET_NB32) + return "lwu\t%0,%R2(%1)"; + else + return "\t%0,%R2(%1)"; } [(set_attr "got" "load") (set_attr "mode" "")]) @@ -5929,7 +5959,10 @@ (define_insn "load_call" (match_operand:P 2 "immediate_operand" "") (reg:SI GOT_VERSION_REGNUM)] UNSPEC_LOAD_CALL))] "TARGET_USE_GOT" - "\t%0,%R2(%1)" + {if (TARGET_NB32) + return "lwu\t%0,%R2(%1)"; + else + return "\t%0,%R2(%1)"; } [(set_attr "got" "load") (set_attr "mode" "")]) Index: gcc/config/mips/mips-protos.h =================================================================== --- gcc/config/mips/mips-protos.h (revision 170267) +++ gcc/config/mips/mips-protos.h (working copy) @@ -339,4 +339,6 @@ typedef rtx (*mulsidi3_gen_fn) (rtx, rtx extern mulsidi3_gen_fn mips_mulsidi3_gen_fn (enum rtx_code); #endif +extern void mips_expand_zero_extend_symbol (rtx, rtx); + #endif /* ! GCC_MIPS_PROTOS_H */ Index: gcc/config/mips/mips.c =================================================================== --- gcc/config/mips/mips.c (revision 170267) +++ gcc/config/mips/mips.c (working copy) @@ -2812,7 +2812,9 @@ mips_split_symbol (rtx temp, rtx addr, e break; default: - high = gen_rtx_HIGH (Pmode, copy_rtx (addr)); + high = gen_rtx_HIGH (ptr_mode, copy_rtx (addr)); + if (GET_MODE (high) != Pmode) + high = gen_rtx_ZERO_EXTEND (Pmode, high); high = mips_force_temporary (temp, high); *low_out = gen_rtx_LO_SUM (Pmode, high, addr); break; @@ -4743,6 +4745,7 @@ mips_get_arg_info (struct mips_arg_info break; case ABI_N32: + case ABI_NB32: case ABI_64: /* Scalar, complex and vector floating-point types are passed in floating-point registers, as long as this is a named rather @@ -8175,6 +8178,8 @@ mips_mdebug_abi_name (void) return "abiO64"; case ABI_N32: return "abiN32"; + case ABI_NB32: + return "abiNB32"; case ABI_64: return "abi64"; case ABI_EABI: @@ -9998,12 +10003,17 @@ mips_emit_loadgp (void) case LOADGP_ABSOLUTE: if (mips_gnu_local_gp == NULL) { - mips_gnu_local_gp = gen_rtx_SYMBOL_REF (Pmode, "__gnu_local_gp"); + mips_gnu_local_gp = gen_rtx_SYMBOL_REF (ptr_mode, "__gnu_local_gp"); SYMBOL_REF_FLAGS (mips_gnu_local_gp) |= SYMBOL_FLAG_LOCAL; } - emit_insn (Pmode == SImode - ? gen_loadgp_absolute_si (pic_reg, mips_gnu_local_gp) - : gen_loadgp_absolute_di (pic_reg, mips_gnu_local_gp)); + if (TARGET_NB32) + { + emit_insn (gen_zero_extendsidi2 (pic_reg, mips_gnu_local_gp)); + } + else + emit_insn (Pmode == SImode + ? gen_loadgp_absolute_si (pic_reg, mips_gnu_local_gp) + : gen_loadgp_absolute_di (pic_reg, mips_gnu_local_gp)); break; case LOADGP_OLDABI: @@ -11233,6 +11243,11 @@ mips_process_load_label (rtx target) mips_multi_add_insn ("addiu\t%@,%@,%%got_ofst(%0)", target, 0); break; + case ABI_NB32: + mips_multi_add_insn ("lwu\t%@,%%got_page(%0)(%+)", target, 0); + mips_multi_add_insn ("daddiu\t%@,%@,%%got_ofst(%0)", target, 0); + break; + case ABI_64: mips_multi_add_insn ("ld\t%@,%%got_page(%0)(%+)", target, 0); mips_multi_add_insn ("daddiu\t%@,%@,%%got_ofst(%0)", target, 0); @@ -15468,6 +15483,8 @@ mips_handle_option (size_t code, const c mips_abi = ABI_O64; else if (strcmp (arg, "n32") == 0) mips_abi = ABI_N32; + else if (strcmp (arg, "nb32") == 0) + mips_abi = ABI_NB32; else if (strcmp (arg, "64") == 0) mips_abi = ABI_64; else if (strcmp (arg, "eabi") == 0) @@ -15985,7 +16002,7 @@ mips_conditional_register_usage (void) } /* Odd registers in the range $f21-$f31 (inclusive) are call-clobbered for n32. */ - if (mips_abi == ABI_N32) + if (mips_abi == ABI_N32 || mips_abi == ABI_NB32) { int regno; for (regno = FP_REG_FIRST + 21; regno <= FP_REG_FIRST + 31; regno+=2) @@ -16400,6 +16417,25 @@ mips_shift_truncation_mask (enum machine return GET_MODE_BITSIZE (mode) - 1; } +void mips_expand_zero_extend_symbol (rtx dest, rtx sym) +{ + rtx t1, t2; + + if (can_create_pseudo_p ()) + { + t1 = gen_reg_rtx (DImode); + t2 = gen_reg_rtx (DImode); + } + else + { + t1 = dest; + t2 = dest; + } + emit_insn (gen_zero_extendsidi_high_address (t1, sym)); + mips_emit_binary (ASHIFT, t2, t1, GEN_INT (16)); + emit_insn (gen_zero_extendsidi_low_address (dest, t2, sym)); +} + /* Initialize the GCC target structure. */ #undef TARGET_ASM_ALIGNED_HI_OP Index: gcc/config/mips/mips.h =================================================================== --- gcc/config/mips/mips.h (revision 170267) +++ gcc/config/mips/mips.h (working copy) @@ -43,6 +43,7 @@ extern int target_flags_explicit; #define ABI_64 2 #define ABI_EABI 3 #define ABI_O64 4 +#define ABI_NB32 5 /* Masks that affect tuning. @@ -303,7 +304,10 @@ enum mips_code_readable_setting { || TUNE_24K) #define TARGET_OLDABI (mips_abi == ABI_32 || mips_abi == ABI_O64) -#define TARGET_NEWABI (mips_abi == ABI_N32 || mips_abi == ABI_64) +#define TARGET_NEWABI (mips_abi == ABI_N32 \ + || mips_abi == ABI_NB32 \ + || mips_abi == ABI_64) +#define TARGET_NB32 (mips_abi == ABI_NB32) /* TARGET_HARD_FLOAT and TARGET_SOFT_FLOAT reflect whether the FPU is directly accessible, while the command-line options select @@ -478,6 +482,11 @@ enum mips_code_readable_setting { builtin_define ("_ABIO64=4"); \ builtin_define ("_MIPS_SIM=_ABIO64"); \ break; \ + \ + case ABI_NB32: \ + builtin_define ("_ABINB32=5"); \ + builtin_define ("_MIPS_SIM=_ABINB32"); \ + break; \ } \ \ builtin_define_with_int_value ("_MIPS_SZINT", INT_TYPE_SIZE); \ @@ -669,6 +678,10 @@ enum mips_code_readable_setting { #define MULTILIB_ABI_DEFAULT "mabi=n32" #endif +#if MIPS_ABI_DEFAULT == ABI_NB32 +#define MULTILIB_ABI_DEFAULT "mabi=nb32" +#endif + #if MIPS_ABI_DEFAULT == ABI_64 #define MULTILIB_ABI_DEFAULT "mabi=64" #endif @@ -742,6 +755,7 @@ enum mips_code_readable_setting { #if MIPS_ABI_DEFAULT == ABI_O64 \ || MIPS_ABI_DEFAULT == ABI_N32 \ + || MIPS_ABI_DEFAULT == ABI_NB32 \ || MIPS_ABI_DEFAULT == ABI_64 #define OPT_ARCH64 "mabi=32|mgp32:;" #define OPT_ARCH32 "mabi=32|mgp32" @@ -1475,7 +1489,7 @@ enum mips_code_readable_setting { /* Pmode is always the same as ptr_mode, but not always the same as word_mode. Extensions of pointers to word_mode must be signed. */ -#define POINTERS_EXTEND_UNSIGNED false +#define POINTERS_EXTEND_UNSIGNED TARGET_NB32 /* Define if loading short immediate values into registers sign extends. */ #define SHORT_IMMEDIATES_SIGN_EXTEND @@ -2430,7 +2444,8 @@ typedef struct mips_args { between pointers and any other objects of this machine mode. */ #ifndef Pmode -#define Pmode (TARGET_64BIT && TARGET_LONG64 ? DImode : SImode) +#define Pmode (TARGET_64BIT && TARGET_LONG64 ? DImode : \ + (TARGET_NB32 ? DImode : SImode)) #endif /* Give call MEMs SImode since it is the "most permissive" mode Index: gcc/config/mips/netbsd.h =================================================================== --- gcc/config/mips/netbsd.h (revision 170267) +++ gcc/config/mips/netbsd.h (working copy) @@ -44,6 +44,8 @@ along with GCC; see the file COPYING3. builtin_define ("__mips_eabi"); \ else if (mips_abi == ABI_N32) \ builtin_define ("__mips_n32"); \ + else if (mips_abi == ABI_NB32) \ + builtin_define ("__mips_nb32"); \ else if (mips_abi == ABI_64) \ builtin_define ("__mips_n64"); \ else if (mips_abi == ABI_O64) \