aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog21
-rw-r--r--gas/config/tc-sh.c111
-rw-r--r--gas/config/tc-sh.h17
-rw-r--r--gas/configure.tgt3
-rw-r--r--gas/doc/c-sh.texi8
-rw-r--r--gas/testsuite/ChangeLog12
-rw-r--r--gas/testsuite/gas/sh/basic.exp4
-rw-r--r--gas/testsuite/gas/sh/fdpic.d13
-rw-r--r--gas/testsuite/gas/sh/fdpic.s8
-rw-r--r--gas/testsuite/gas/sh/reg-prefix.d5
-rw-r--r--gas/testsuite/gas/sh/sh2a-pic.d16
-rw-r--r--gas/testsuite/gas/sh/sh2a-pic.s6
-rw-r--r--gas/testsuite/lib/gas-defs.exp1
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*] \