diff options
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 21 | ||||
-rw-r--r-- | gas/config/tc-sh.c | 111 | ||||
-rw-r--r-- | gas/config/tc-sh.h | 17 | ||||
-rw-r--r-- | gas/configure.tgt | 3 | ||||
-rw-r--r-- | gas/doc/c-sh.texi | 8 | ||||
-rw-r--r-- | gas/testsuite/ChangeLog | 12 | ||||
-rw-r--r-- | gas/testsuite/gas/sh/basic.exp | 4 | ||||
-rw-r--r-- | gas/testsuite/gas/sh/fdpic.d | 13 | ||||
-rw-r--r-- | gas/testsuite/gas/sh/fdpic.s | 8 | ||||
-rw-r--r-- | gas/testsuite/gas/sh/reg-prefix.d | 5 | ||||
-rw-r--r-- | gas/testsuite/gas/sh/sh2a-pic.d | 16 | ||||
-rw-r--r-- | gas/testsuite/gas/sh/sh2a-pic.s | 6 | ||||
-rw-r--r-- | gas/testsuite/lib/gas-defs.exp | 1 |
13 files changed, 201 insertions, 24 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 028388d..9779979 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,24 @@ +2010-05-25 Daniel Jacobowitz <dan@codesourcery.com> + Joseph Myers <joseph@codesourcery.com> + Andrew Stubbs <ams@codesourcery.com> + + * config/tc-sh.c (sh_fdpic): New. + (sh_check_fixup): Handle relocations on movi20. + (parse_exp): Do not reject PIC operators here. + (build_Mytes): Check for unhandled PIC operators here. Use + sh_check_fixup for movi20. + (enum options): Add OPTION_FDPIC. + (md_longopts, md_parse_option, md_show_usage): Add --fdpic. + (sh_fix_adjustable, md_apply_fix): Handle FDPIC and movi20 relocations. + (sh_elf_final_processing): Handle --fdpic. + (sh_uclinux_target_format): New. + (sh_parse_name): Handle FDPIC relocation operators. + * config/tc-sh.h (TARGET_FORMAT): Define specially for TE_UCLINUX. + (sh_uclinux_target_format): Declare for TE_UCLINUX. + * configure.tgt (sh-*-uclinux* | sh[12]-*-uclinux*): Set + em=uclinux. + * doc/c-sh.texi (SH Options): Document --fdpic. + 2010-05-25 Jay Krell <jay.krell@cornell.edu> PR ld/11621 diff --git a/gas/config/tc-sh.c b/gas/config/tc-sh.c index a7cdd0e..4e49e4e 100644 --- a/gas/config/tc-sh.c +++ b/gas/config/tc-sh.c @@ -145,6 +145,9 @@ static unsigned int preset_target_arch; accommodate the insns seen so far. */ static unsigned int valid_arch; +/* Whether --fdpic was given. */ +static int sh_fdpic; + const char EXP_CHARS[] = "eE"; /* Chars that mean this number is a floating point constant. */ @@ -612,7 +615,6 @@ sh_check_fixup (expressionS *main_exp, bfd_reloc_code_real_type *r_type_p) if (exp->X_op == O_PIC_reloc) { -#ifdef HAVE_SH64 switch (*r_type_p) { case BFD_RELOC_NONE: @@ -620,6 +622,31 @@ sh_check_fixup (expressionS *main_exp, bfd_reloc_code_real_type *r_type_p) *r_type_p = exp->X_md; break; + case BFD_RELOC_SH_DISP20: + switch (exp->X_md) + { + case BFD_RELOC_32_GOT_PCREL: + *r_type_p = BFD_RELOC_SH_GOT20; + break; + + case BFD_RELOC_32_GOTOFF: + *r_type_p = BFD_RELOC_SH_GOTOFF20; + break; + + case BFD_RELOC_SH_GOTFUNCDESC: + *r_type_p = BFD_RELOC_SH_GOTFUNCDESC20; + break; + + case BFD_RELOC_SH_GOTOFFFUNCDESC: + *r_type_p = BFD_RELOC_SH_GOTOFFFUNCDESC20; + break; + + default: + abort (); + } + break; + +#ifdef HAVE_SH64 case BFD_RELOC_SH_IMM_LOW16: switch (exp->X_md) { @@ -715,13 +742,11 @@ sh_check_fixup (expressionS *main_exp, bfd_reloc_code_real_type *r_type_p) abort (); } break; +#endif default: abort (); } -#else - *r_type_p = exp->X_md; -#endif if (exp == main_exp) exp->X_op = O_symbol; else @@ -1358,12 +1383,6 @@ parse_exp (char *s, sh_operand_info *op) expression (&op->immediate); if (op->immediate.X_op == O_absent) as_bad (_("missing operand")); -#ifdef OBJ_ELF - else if (op->immediate.X_op == O_PIC_reloc - || sh_PIC_related_p (op->immediate.X_add_symbol) - || sh_PIC_related_p (op->immediate.X_op_symbol)) - as_bad (_("misplaced PIC operand")); -#endif new_pointer = input_line_pointer; input_line_pointer = save; return new_pointer; @@ -2327,6 +2346,8 @@ build_Mytes (sh_opcode_info *opcode, sh_operand_info *operand) unsigned int size = 2; int low_byte = target_big_endian ? 1 : 0; int max_index = 4; + bfd_reloc_code_real_type r_type; + int unhandled_pic = 0; nbuf[0] = 0; nbuf[1] = 0; @@ -2337,6 +2358,14 @@ build_Mytes (sh_opcode_info *opcode, sh_operand_info *operand) nbuf[6] = 0; nbuf[7] = 0; + for (indx = 0; indx < 3; indx++) + if (opcode->arg[indx] == A_IMM + && operand[indx].type == A_IMM + && (operand[indx].immediate.X_op == O_PIC_reloc + || sh_PIC_related_p (operand[indx].immediate.X_add_symbol) + || sh_PIC_related_p (operand[indx].immediate.X_op_symbol))) + unhandled_pic = 1; + if (SH_MERGE_ARCH_SET (opcode->arch, arch_op32)) { output = frag_more (4); @@ -2415,7 +2444,11 @@ build_Mytes (sh_opcode_info *opcode, sh_operand_info *operand) case IMM0_20_4: break; case IMM0_20: - insert4 (output, BFD_RELOC_SH_DISP20, 0, operand); + r_type = BFD_RELOC_SH_DISP20; + if (sh_check_fixup (&operand->immediate, &r_type)) + as_bad (_("Invalid PIC expression.")); + unhandled_pic = 0; + insert4 (output, r_type, 0, operand); break; case IMM0_20BY8: insert4 (output, BFD_RELOC_SH_DISP20BY8, 0, operand); @@ -2474,6 +2507,8 @@ build_Mytes (sh_opcode_info *opcode, sh_operand_info *operand) } } } + if (unhandled_pic) + as_bad (_("misplaced PIC operand")); if (!target_big_endian) { output[1] = (nbuf[0] << 4) | (nbuf[1]); @@ -3098,6 +3133,9 @@ enum options OPTION_PT32, #endif OPTION_H_TICK_HEX, +#ifdef OBJ_ELF + OPTION_FDPIC, +#endif OPTION_DUMMY /* Not used. This is just here to make it easy to add and subtract options from this enum. */ }; @@ -3126,6 +3164,10 @@ struct option md_longopts[] = #endif /* HAVE_SH64 */ { "h-tick-hex", no_argument, NULL, OPTION_H_TICK_HEX }, +#ifdef OBJ_ELF + {"fdpic", no_argument, NULL, OPTION_FDPIC}, +#endif + {NULL, no_argument, NULL, 0} }; size_t md_longopts_size = sizeof (md_longopts); @@ -3259,6 +3301,12 @@ md_parse_option (int c, char *arg ATTRIBUTE_UNUSED) enable_h_tick_hex = 1; break; +#ifdef OBJ_ELF + case OPTION_FDPIC: + sh_fdpic = TRUE; + break; +#endif /* OBJ_ELF */ + default: return 0; } @@ -3311,6 +3359,10 @@ SH options:\n\ --expand-pt32 with -abi=64, expand PT, PTA and PTB instructions\n\ to 32 bits only\n")); #endif /* HAVE_SH64 */ +#ifdef OBJ_ELF + fprintf (stream, _("\ +--fdpic generate an FDPIC object file\n")); +#endif /* OBJ_ELF */ } /* This struct is used to pass arguments to sh_count_relocs through @@ -3804,7 +3856,13 @@ sh_fix_adjustable (fixS *fixP) { if (fixP->fx_r_type == BFD_RELOC_32_PLT_PCREL || fixP->fx_r_type == BFD_RELOC_32_GOT_PCREL + || fixP->fx_r_type == BFD_RELOC_SH_GOT20 || fixP->fx_r_type == BFD_RELOC_SH_GOTPC + || fixP->fx_r_type == BFD_RELOC_SH_GOTFUNCDESC + || fixP->fx_r_type == BFD_RELOC_SH_GOTFUNCDESC20 + || fixP->fx_r_type == BFD_RELOC_SH_GOTOFFFUNCDESC + || fixP->fx_r_type == BFD_RELOC_SH_GOTOFFFUNCDESC20 + || fixP->fx_r_type == BFD_RELOC_SH_FUNCDESC || ((fixP->fx_r_type == BFD_RELOC_32) && dont_adjust_reloc_32) || fixP->fx_r_type == BFD_RELOC_RVA) return 0; @@ -3843,6 +3901,22 @@ sh_elf_final_processing (void) elf_elfheader (stdoutput)->e_flags &= ~EF_SH_MACH_MASK; elf_elfheader (stdoutput)->e_flags |= val; + + if (sh_fdpic) + elf_elfheader (stdoutput)->e_flags |= EF_SH_FDPIC; +} +#endif + +#ifdef TE_UCLINUX +/* Return the target format for uClinux. */ + +const char * +sh_uclinux_target_format (void) +{ + if (sh_fdpic) + return (!target_big_endian ? "elf32-sh-fdpic" : "elf32-shbig-fdpic"); + else + return (!target_big_endian ? "elf32-shl" : "elf32-sh"); } #endif @@ -4151,7 +4225,13 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) S_SET_THREAD_LOCAL (fixP->fx_addsy); /* Fallthrough */ case BFD_RELOC_32_GOT_PCREL: + case BFD_RELOC_SH_GOT20: case BFD_RELOC_SH_GOTPLT32: + case BFD_RELOC_SH_GOTFUNCDESC: + case BFD_RELOC_SH_GOTFUNCDESC20: + case BFD_RELOC_SH_GOTOFFFUNCDESC: + case BFD_RELOC_SH_GOTOFFFUNCDESC20: + case BFD_RELOC_SH_FUNCDESC: * valP = 0; /* Fully resolved at runtime. No addend. */ apply_full_field_fix (fixP, buf, 0, 4); break; @@ -4161,6 +4241,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) S_SET_THREAD_LOCAL (fixP->fx_addsy); /* Fallthrough */ case BFD_RELOC_32_GOTOFF: + case BFD_RELOC_SH_GOTOFF20: apply_full_field_fix (fixP, buf, val, 4); break; #endif @@ -4468,6 +4549,14 @@ sh_parse_name (char const *name, reloc_type = BFD_RELOC_SH_TLS_LE_32; else if ((next_end = sh_end_of_match (next + 1, "DTPOFF"))) reloc_type = BFD_RELOC_SH_TLS_LDO_32; + else if ((next_end = sh_end_of_match (next + 1, "PCREL"))) + reloc_type = BFD_RELOC_32_PCREL; + else if ((next_end = sh_end_of_match (next + 1, "GOTFUNCDESC"))) + reloc_type = BFD_RELOC_SH_GOTFUNCDESC; + else if ((next_end = sh_end_of_match (next + 1, "GOTOFFFUNCDESC"))) + reloc_type = BFD_RELOC_SH_GOTOFFFUNCDESC; + else if ((next_end = sh_end_of_match (next + 1, "FUNCDESC"))) + reloc_type = BFD_RELOC_SH_FUNCDESC; else goto no_suffix; diff --git a/gas/config/tc-sh.h b/gas/config/tc-sh.h index 1b5ec26..2a69627 100644 --- a/gas/config/tc-sh.h +++ b/gas/config/tc-sh.h @@ -1,6 +1,6 @@ /* This file is tc-sh.h Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, - 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + 2003, 2004, 2005, 2006, 2007, 2008, 2010 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -134,7 +134,7 @@ extern void sh_frob_file (void); #define COFF_MAGIC (!target_big_endian ? SH_ARCH_MAGIC_LITTLE : SH_ARCH_MAGIC_BIG) -#define tc_coff_symbol_emit_hook(a) ; /* not used */ +#define tc_coff_symbol_emit_hook(a) ; /* Not used. */ #define TC_KEEP_FX_OFFSET 1 @@ -155,7 +155,7 @@ extern void sh_frob_file (void); #ifdef OBJ_ELF /* ELF specific definitions. */ -/* Whether or not the target is big endian */ +/* Whether or not the target is big endian. */ extern int target_big_endian; #ifdef TE_LINUX #define TARGET_FORMAT (!target_big_endian ? "elf32-sh-linux" : "elf32-shbig-linux") @@ -165,6 +165,9 @@ extern int target_big_endian; #define TARGET_FORMAT (!target_big_endian ? "elf32-shl-symbian" : "elf32-sh-symbian") #elif defined (TE_VXWORKS) #define TARGET_FORMAT (!target_big_endian ? "elf32-shl-vxworks" : "elf32-sh-vxworks") +#elif defined (TE_UCLINUX) +#define TARGET_FORMAT sh_uclinux_target_format () +extern const char * sh_uclinux_target_format (void); #else #define TARGET_FORMAT (!target_big_endian ? "elf32-shl" : "elf32-sh") #endif @@ -172,7 +175,7 @@ extern int target_big_endian; #define elf_tc_final_processing sh_elf_final_processing extern void sh_elf_final_processing (void); -#define DIFF_EXPR_OK /* foo-. gets turned into PC relative relocs */ +#define DIFF_EXPR_OK /* foo-. gets turned into PC relative relocs. */ #define GLOBAL_OFFSET_TABLE_NAME "_GLOBAL_OFFSET_TABLE_" @@ -227,8 +230,8 @@ extern bfd_boolean sh_fix_adjustable (struct fix *); #define md_parse_name(name, exprP, mode, nextcharP) \ sh_parse_name ((name), (exprP), (mode), (nextcharP)) -int sh_parse_name (char const *name, expressionS *exprP, - enum expr_mode mode, char *nextchar); +int sh_parse_name (char const *, expressionS *, + enum expr_mode, char *); #define TC_CONS_FIX_NEW(FRAG, OFF, LEN, EXP) \ sh_cons_fix_new ((FRAG), (OFF), (LEN), (EXP)) @@ -244,7 +247,7 @@ void sh_cons_fix_new (fragS *, int, int, expressionS *); extern void sh_cfi_frame_initial_instructions (void); #define tc_regname_to_dw2regnum sh_regname_to_dw2regnum -extern int sh_regname_to_dw2regnum (char *regname); +extern int sh_regname_to_dw2regnum (char *); /* All SH instructions are multiples of 16 bits. */ #define DWARF2_LINE_MIN_INSN_LENGTH 2 diff --git a/gas/configure.tgt b/gas/configure.tgt index 23d8662..77cbac1 100644 --- a/gas/configure.tgt +++ b/gas/configure.tgt @@ -360,7 +360,8 @@ case ${generic_target} in *) endian=big ;; esac ;; sh*-*-symbianelf*) fmt=elf endian=little ;; - sh-*-elf* | sh-*-uclinux* | sh[12]-*-uclinux*) fmt=elf ;; + sh-*-elf*) fmt=elf ;; + sh-*-uclinux* | sh[12]-*-uclinux*) fmt=elf em=uclinux ;; sh-*-coff*) fmt=coff ;; sh-*-nto*) fmt=elf ;; sh-*-pe*) fmt=coff em=pe bfd_gas=yes endian=little ;; diff --git a/gas/doc/c-sh.texi b/gas/doc/c-sh.texi index 00c95d7..619f022 100644 --- a/gas/doc/c-sh.texi +++ b/gas/doc/c-sh.texi @@ -1,5 +1,5 @@ -@c Copyright 1991, 1992, 1993, 1994, 1995, 1997, 2001, 2003, 2004, 2005, 2008 -@c Free Software Foundation, Inc. +@c Copyright 1991, 1992, 1993, 1994, 1995, 1997, 2001, 2003, 2004, +@c 2005, 2008, 2010 Free Software Foundation, Inc. @c This is part of the GAS manual. @c For copying conditions, see the file as.texinfo. @page @@ -54,6 +54,10 @@ Renesas assembler. @item --allow-reg-prefix Allow '$' as a register name prefix. +@kindex --fdpic +@item --fdpic +Generate an FDPIC object file. + @item --isa=sh4 | sh4a Specify the sh4 or sh4a instruction set. @item --isa=dsp diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 59f9830..5d2a4f3 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,15 @@ +2010-05-25 Daniel Jacobowitz <dan@codesourcery.com> + Joseph Myers <joseph@codesourcery.com> + Andrew Stubbs <ams@codesourcery.com> + + * gas/sh/basic.exp: Run new tests. Handle uClinux like Linux. + * gas/sh/fdpic.d: New file. + * gas/sh/fdpic.s: New file. + * gas/sh/reg-prefix.d: Force big-endian. + * gas/sh/sh2a-pic.d: New file. + * gas/sh/sh2a-pic.s: New file. + * lib/gas-defs.exp (is_elf_format): Include sh*-*-uclinux*. + 2010-05-18 H.J. Lu <hongjiu.lu@intel.com> PR gas/11600 diff --git a/gas/testsuite/gas/sh/basic.exp b/gas/testsuite/gas/sh/basic.exp index 3bb7931..2daa038 100644 --- a/gas/testsuite/gas/sh/basic.exp +++ b/gas/testsuite/gas/sh/basic.exp @@ -142,7 +142,7 @@ if [istarget sh*-*-*] then { run_dump_test "pcrel2" } - if {[istarget sh*-*elf] || [istarget sh*-linux*]} then { + if {[istarget sh*-*elf] || [istarget sh*-*linux*]} then { if {![istarget "sh64*-*-*"] && ![istarget "sh5*-*-*"]} then { run_dump_test "sh4a" run_dump_test "sh4a-fp" @@ -151,9 +151,11 @@ if [istarget sh*-*-*] then { run_dump_test "sh4al-dsp" run_dump_test "sh2a" + run_dump_test "sh2a-pic" } run_dump_test "pic" + run_dump_test "fdpic" # Test TLS. run_dump_test "tlsd" diff --git a/gas/testsuite/gas/sh/fdpic.d b/gas/testsuite/gas/sh/fdpic.d new file mode 100644 index 0000000..33dfc71 --- /dev/null +++ b/gas/testsuite/gas/sh/fdpic.d @@ -0,0 +1,13 @@ +#objdump: -dr --prefix-addresses --show-raw-insn +#name: FDPIC relocations + +dump.o: file format elf32-sh.* + +Disassembly of section .text: + \.\.\. + 0: R_SH_REL32 foo + 4: R_SH_FUNCDESC foo + 8: R_SH_GOT32 foo + c: R_SH_GOTOFF foo + 10: R_SH_GOTFUNCDESC foo + 14: R_SH_GOTOFFFUNCDESC foo diff --git a/gas/testsuite/gas/sh/fdpic.s b/gas/testsuite/gas/sh/fdpic.s new file mode 100644 index 0000000..7a7ad0f --- /dev/null +++ b/gas/testsuite/gas/sh/fdpic.s @@ -0,0 +1,8 @@ + .text + + .long foo@PCREL + .long foo@FUNCDESC + .long foo@GOT + .long foo@GOTOFF + .long foo@GOTFUNCDESC + .long foo@GOTOFFFUNCDESC diff --git a/gas/testsuite/gas/sh/reg-prefix.d b/gas/testsuite/gas/sh/reg-prefix.d index 1821bbc..a42e8c4 100644 --- a/gas/testsuite/gas/sh/reg-prefix.d +++ b/gas/testsuite/gas/sh/reg-prefix.d @@ -1,10 +1,11 @@ #objdump: -dr --prefix-addresses --show-raw-insn -#as: --allow-reg-prefix -little +#as: --allow-reg-prefix -big #name: SH --allow-reg-prefix option +#skip: sh*-*-symbian* # Test SH register names prefixed with $: .*: file format elf.*sh.* Disassembly of section .text: -0x00000000 12 60 mov\.l @r1,r0 +0x00000000 60 12 mov\.l @r1,r0 diff --git a/gas/testsuite/gas/sh/sh2a-pic.d b/gas/testsuite/gas/sh/sh2a-pic.d new file mode 100644 index 0000000..c7fe12b --- /dev/null +++ b/gas/testsuite/gas/sh/sh2a-pic.d @@ -0,0 +1,16 @@ +#objdump: -dr --prefix-addresses --show-raw-insn +#name: SH2a PIC relocations +#as: -isa=sh2a +#skip: sh*-*-symbian* + +dump.o: file format elf32-sh.* + +Disassembly of section .text: +0x00000000 01 00 00 00 movi20 #0,r1 + 0: R_SH_GOT20 foo +0x00000004 01 00 00 00 movi20 #0,r1 + 4: R_SH_GOTOFF20 foo +0x00000008 01 00 00 00 movi20 #0,r1 + 8: R_SH_GOTFUNCDESC20 foo +0x0000000c 01 00 00 00 movi20 #0,r1 + c: R_SH_GOTOFFFUNCDESC20 foo diff --git a/gas/testsuite/gas/sh/sh2a-pic.s b/gas/testsuite/gas/sh/sh2a-pic.s new file mode 100644 index 0000000..888a7c9 --- /dev/null +++ b/gas/testsuite/gas/sh/sh2a-pic.s @@ -0,0 +1,6 @@ + .text + + movi20 #foo@GOT, r1 + movi20 #foo@GOTOFF, r1 + movi20 #foo@GOTFUNCDESC, r1 + movi20 #foo@GOTOFFFUNCDESC, r1 diff --git a/gas/testsuite/lib/gas-defs.exp b/gas/testsuite/lib/gas-defs.exp index 0506b94..fd2f179 100644 --- a/gas/testsuite/lib/gas-defs.exp +++ b/gas/testsuite/lib/gas-defs.exp @@ -289,6 +289,7 @@ proc is_elf_format {} { && ![istarget hppa*64*-*-hpux*] \ && ![istarget *-*-linux*] \ && ![istarget frv-*-uclinux*] \ + && ![istarget sh*-*-uclinux*] \ && ![istarget *-*-irix5*] \ && ![istarget *-*-irix6*] \ && ![istarget *-*-netbsd*] \ |