aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gas/ChangeLog25
-rw-r--r--gas/Makefile.am12
-rw-r--r--gas/Makefile.in12
-rw-r--r--gas/config/bfin-defs.h1
-rw-r--r--gas/config/bfin-lex.l2
-rw-r--r--gas/config/bfin-parse.y26
-rw-r--r--gas/config/tc-bfin.c192
7 files changed, 207 insertions, 63 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index b12c440..b83b26f 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,28 @@
+2006-03-25 Bernd Schmidt <bernd.schmidt@analog.com>
+
+ * config/bfin-defs.h (Expr_Node_Type enum): Add Expr_Node_GOT_Reloc.
+ * config/bfin-lex.l: Recognize GOT17M4 and FUNCDESC_GOT17M4.
+ * config/bfin-parse.y: Include "libbfd.h", "elf/common.h" and
+ "elf/bfin.h".
+ (GOT17M4, FUNCDESC_GOT17M4): New tokens of type <value>.
+ (any_gotrel): New rule.
+ (got): Use it, and create Expr_Node_GOT_Reloc nodes.
+ * config/tc-bfin.c: Include "libbfd.h", "elf/common.h" and
+ "elf/bfin.h".
+ (DEFAULT_FLAGS, bfin_flags, bfin_pic_flag): New.
+ (bfin_pic_ptr): New function.
+ (md_pseudo_table): Add it for ".picptr".
+ (OPTION_FDPIC): New macro.
+ (md_longopts): Add -mfdpic.
+ (md_parse_option): Handle it.
+ (md_begin): Set BFD flags.
+ (md_apply_fix3, bfin_fix_adjustable): Handle new relocs.
+ (bfin_gen_ldstidxi): Adjust to match the trees that the parser gives
+ us for GOT relocs.
+ * Makefile.am (bfin-parse.o): Update dependencies.
+ (DEPTC_bfin_elf): Likewise.
+ * Makefile.in: Regenerate.
+
2006-03-25 Richard Sandiford <richard@codesourcery.com>
* config/tc-m68k.c (m68k_cpus): Change cpu_cf5208 entries to use
diff --git a/gas/Makefile.am b/gas/Makefile.am
index 4cd7e26..525ebbb 100644
--- a/gas/Makefile.am
+++ b/gas/Makefile.am
@@ -613,7 +613,8 @@ $(srcdir)/config/m68k-parse.h: ; @true
bfin-parse.c: $(srcdir)/config/bfin-parse.y
$(SHELL) $(YLWRAP) $(srcdir)/config/bfin-parse.y y.tab.c bfin-parse.c y.tab.h bfin-parse.h -- $(YACCCOMPILE) -d ;
bfin-parse.h: bfin-parse.c
-bfin-parse.o: bfin-parse.c bfin-parse.h $(srcdir)/config/bfin-defs.h
+bfin-parse.o: bfin-parse.c bfin-parse.h $(srcdir)/config/bfin-defs.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/bfin.h $(BFDDIR)/libbfd.h
bfin-defs.h: ; @true
$(srcdir)/config/bfin-defs.h: ; @true
@@ -1021,14 +1022,17 @@ DEPTC_bfin_coff = $(INCDIR)/symcat.h $(srcdir)/config/obj-coff.h \
$(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h struc-symbol.h \
$(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h \
$(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h dwarf2dbg.h \
- $(srcdir)/config/bfin-defs.h $(INCDIR)/obstack.h $(INCDIR)/safe-ctype.h \
- $(srcdir)/config/bfin-aux.h $(INCDIR)/opcode/bfin.h
+ $(INCDIR)/obstack.h $(INCDIR)/safe-ctype.h \
+ $(srcdir)/config/bfin-aux.h $(INCDIR)/opcode/bfin.h \
+ $(srcdir)/config/bfin-defs.h $(INCDIR)/elf/common.h \
+ $(INCDIR)/elf/bfin.h $(BFDDIR)/libbfd.h
DEPTC_bfin_elf = $(INCDIR)/symcat.h $(srcdir)/config/obj-elf.h \
$(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
$(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-bfin.h \
dwarf2dbg.h struc-symbol.h $(srcdir)/config/bfin-defs.h \
$(INCDIR)/obstack.h $(INCDIR)/safe-ctype.h $(srcdir)/config/bfin-aux.h \
- $(INCDIR)/opcode/bfin.h
+ $(INCDIR)/opcode/bfin.h $(srcdir)/config/bfin-defs.h $(INCDIR)/elf/common.h \
+ $(INCDIR)/elf/bfin.h $(BFDDIR)/libbfd.h
DEPTC_cris_aout = $(INCDIR)/symcat.h $(srcdir)/config/obj-aout.h \
$(srcdir)/config/tc-cris.h $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h \
$(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h \
diff --git a/gas/Makefile.in b/gas/Makefile.in
index 9dde01c..fc2b9b4 100644
--- a/gas/Makefile.in
+++ b/gas/Makefile.in
@@ -802,15 +802,18 @@ DEPTC_bfin_coff = $(INCDIR)/symcat.h $(srcdir)/config/obj-coff.h \
$(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h struc-symbol.h \
$(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h \
$(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h dwarf2dbg.h \
- $(srcdir)/config/bfin-defs.h $(INCDIR)/obstack.h $(INCDIR)/safe-ctype.h \
- $(srcdir)/config/bfin-aux.h $(INCDIR)/opcode/bfin.h
+ $(INCDIR)/obstack.h $(INCDIR)/safe-ctype.h \
+ $(srcdir)/config/bfin-aux.h $(INCDIR)/opcode/bfin.h \
+ $(srcdir)/config/bfin-defs.h $(INCDIR)/elf/common.h \
+ $(INCDIR)/elf/bfin.h $(BFDDIR)/libbfd.h
DEPTC_bfin_elf = $(INCDIR)/symcat.h $(srcdir)/config/obj-elf.h \
$(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
$(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-bfin.h \
dwarf2dbg.h struc-symbol.h $(srcdir)/config/bfin-defs.h \
$(INCDIR)/obstack.h $(INCDIR)/safe-ctype.h $(srcdir)/config/bfin-aux.h \
- $(INCDIR)/opcode/bfin.h
+ $(INCDIR)/opcode/bfin.h $(srcdir)/config/bfin-defs.h $(INCDIR)/elf/common.h \
+ $(INCDIR)/elf/bfin.h $(BFDDIR)/libbfd.h
DEPTC_cris_aout = $(INCDIR)/symcat.h $(srcdir)/config/obj-aout.h \
$(srcdir)/config/tc-cris.h $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h \
@@ -2966,7 +2969,8 @@ $(srcdir)/config/m68k-parse.h: ; @true
bfin-parse.c: $(srcdir)/config/bfin-parse.y
$(SHELL) $(YLWRAP) $(srcdir)/config/bfin-parse.y y.tab.c bfin-parse.c y.tab.h bfin-parse.h -- $(YACCCOMPILE) -d ;
bfin-parse.h: bfin-parse.c
-bfin-parse.o: bfin-parse.c bfin-parse.h $(srcdir)/config/bfin-defs.h
+bfin-parse.o: bfin-parse.c bfin-parse.h $(srcdir)/config/bfin-defs.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/bfin.h $(BFDDIR)/libbfd.h
bfin-defs.h: ; @true
$(srcdir)/config/bfin-defs.h: ; @true
diff --git a/gas/config/bfin-defs.h b/gas/config/bfin-defs.h
index 46ae61e..48bacb3 100644
--- a/gas/config/bfin-defs.h
+++ b/gas/config/bfin-defs.h
@@ -263,6 +263,7 @@ typedef enum
Expr_Node_Binop, /* Binary operator. */
Expr_Node_Unop, /* Unary operator. */
Expr_Node_Reloc, /* Symbol to be relocated. */
+ Expr_Node_GOT_Reloc, /* Symbol to be relocated using the GOT. */
Expr_Node_Constant /* Constant. */
} Expr_Node_Type;
diff --git a/gas/config/bfin-lex.l b/gas/config/bfin-lex.l
index c3af842..3a0077c 100644
--- a/gas/config/bfin-lex.l
+++ b/gas/config/bfin-lex.l
@@ -241,6 +241,8 @@ abort return ABORT;
[aA]0"."[wW] _REG.regno = REG_A0w; return REG;
[aA]0 _REG.regno = REG_A0; return REG_A_DOUBLE_ZERO;
[Gg][Oo][Tt] return GOT;
+[Gg][Oo][Tt]"17"[Mm]"4" return GOT17M4;
+[Ff][Uu][Nn][Cc][Dd][Ee][Ss][Cc]"_"[Gg][Oo][Tt]"17"[Mm]"4" return FUNCDESC_GOT17M4;
[Pp][Ll][Tt][Pp][Cc] return PLTPC;
diff --git a/gas/config/bfin-parse.y b/gas/config/bfin-parse.y
index f1e4887..917c2d2 100644
--- a/gas/config/bfin-parse.y
+++ b/gas/config/bfin-parse.y
@@ -21,10 +21,14 @@
%{
#include <stdio.h>
-#include "bfin-aux.h"
#include <stdarg.h>
#include <obstack.h>
+#include "bfin-aux.h" // opcode generating auxiliaries
+#include "libbfd.h"
+#include "elf/common.h"
+#include "elf/bfin.h"
+
#define DSP32ALU(aopcde, HL, dst1, dst0, src0, src1, s, x, aop) \
bfin_gen_dsp32alu (HL, aopcde, aop, s, x, dst0, dst1, src0, src1)
@@ -485,7 +489,8 @@ is_group2 (INSTR_T x)
%token STATUS_REG
%token MNOP
%token SYMBOL NUMBER
-%token GOT AT PLTPC
+%token GOT GOT17M4 FUNCDESC_GOT17M4
+%token AT PLTPC
/* Types. */
%type <instr> asm
@@ -544,7 +549,7 @@ is_group2 (INSTR_T x)
%type <expr> got
%type <expr> got_or_expr
%type <expr> pltpc
-
+%type <value> any_gotrel GOT GOT17M4 FUNCDESC_GOT17M4
/* Precedence rules. */
%left BAR
@@ -4111,9 +4116,20 @@ symbol: SYMBOL
}
;
-got: symbol AT GOT
+any_gotrel:
+ GOT
+ { $$ = BFD_RELOC_BFIN_GOT; }
+ | GOT17M4
+ { $$ = BFD_RELOC_BFIN_GOT17M4; }
+ | FUNCDESC_GOT17M4
+ { $$ = BFD_RELOC_BFIN_FUNCDESC_GOT17M4; }
+ ;
+
+got: symbol AT any_gotrel
{
- $$ = $1;
+ Expr_Node_Value val;
+ val.i_value = $3;
+ $$ = Expr_Node_Create (Expr_Node_GOT_Reloc, val, $1, NULL);
}
;
diff --git a/gas/config/tc-bfin.c b/gas/config/tc-bfin.c
index d9e88de..43d48d6 100644
--- a/gas/config/tc-bfin.c
+++ b/gas/config/tc-bfin.c
@@ -28,6 +28,9 @@
#ifdef OBJ_ELF
#include "dwarf2dbg.h"
#endif
+#include "libbfd.h"
+#include "elf/common.h"
+#include "elf/bfin.h"
extern int yyparse (void);
struct yy_buffer_state;
@@ -45,6 +48,12 @@ int last_insn_size;
extern struct obstack mempool;
FILE *errorf;
+/* Flags to set in the elf header */
+#define DEFAULT_FLAGS 0
+
+static flagword bfin_flags = DEFAULT_FLAGS;
+static const char *bfin_pic_flag = (const char *)0;
+
/* Registers list. */
struct bfin_reg_entry
{
@@ -202,11 +211,73 @@ static const struct bfin_reg_entry bfin_reg_info[] = {
{0, 0}
};
+/* Blackfin specific function to handle FD-PIC pointer initializations. */
+
+static void
+bfin_pic_ptr (int nbytes)
+{
+ expressionS exp;
+ char *p;
+
+ if (nbytes != 4)
+ abort ();
+
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
+
+ if (is_it_end_of_statement ())
+ {
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+#ifdef md_cons_align
+ md_cons_align (nbytes);
+#endif
+
+ do
+ {
+ bfd_reloc_code_real_type reloc_type = BFD_RELOC_BFIN_FUNCDESC;
+
+ if (strncasecmp (input_line_pointer, "funcdesc(", 9) == 0)
+ {
+ input_line_pointer += 9;
+ expression (&exp);
+ if (*input_line_pointer == ')')
+ input_line_pointer++;
+ else
+ as_bad ("missing ')'");
+ }
+ else
+ error ("missing funcdesc in picptr");
+
+ p = frag_more (4);
+ memset (p, 0, 4);
+ fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &exp, 0,
+ reloc_type);
+ }
+ while (*input_line_pointer++ == ',');
+
+ input_line_pointer--; /* Put terminator back into stream. */
+ demand_empty_rest_of_line ();
+}
+
+static void
+bfin_s_bss (int ignore ATTRIBUTE_UNUSED)
+{
+ register int temp;
+
+ temp = get_absolute_expression ();
+ subseg_set (bss_section, (subsegT) temp);
+ demand_empty_rest_of_line ();
+}
const pseudo_typeS md_pseudo_table[] = {
{"align", s_align_bytes, 0},
{"byte2", cons, 2},
{"byte4", cons, 4},
+ {"picptr", bfin_pic_ptr, 4},
{"code", obj_elf_section, 0},
{"db", cons, 1},
{"dd", cons, 4},
@@ -218,17 +289,6 @@ const pseudo_typeS md_pseudo_table[] = {
{0, 0, 0}
};
-static void
-bfin_s_bss (int ignore ATTRIBUTE_UNUSED)
-{
- register int temp;
-
- temp = get_absolute_expression ();
- subseg_set (bss_section, (subsegT) temp);
- demand_empty_rest_of_line ();
-}
-
-
/* Characters that are used to denote comments and line separators. */
const char comment_chars[] = "";
const char line_comment_chars[] = "#";
@@ -245,16 +305,32 @@ const char FLT_CHARS[] = "fFdDxX";
/* Define bfin-specific command-line options (there are none). */
const char *md_shortopts = "";
-struct option md_longopts[] = {
- {NULL, no_argument, NULL, 0}
+#define OPTION_FDPIC (OPTION_MD_BASE)
+
+struct option md_longopts[] =
+{
+ { "mfdpic", no_argument, NULL, OPTION_FDPIC },
+ { NULL, no_argument, NULL, 0 },
};
+
size_t md_longopts_size = sizeof (md_longopts);
int
md_parse_option (int c ATTRIBUTE_UNUSED, char *arg ATTRIBUTE_UNUSED)
{
- return 0;
+ switch (c)
+ {
+ default:
+ return 0;
+
+ case OPTION_FDPIC:
+ bfin_flags |= EF_BFIN_FDPIC;
+ bfin_pic_flag = "-mfdpic";
+ break;
+ }
+
+ return 1;
}
void
@@ -267,6 +343,10 @@ md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
void
md_begin ()
{
+ /* Set the ELF flags if desired. */
+ if (bfin_flags)
+ bfd_set_private_flags (stdoutput, bfin_flags);
+
/* Set the default machine type. */
if (!bfd_set_arch_mach (stdoutput, bfd_arch_bfin, 0))
as_warn ("Could not set architecture and machine.");
@@ -476,6 +556,8 @@ md_apply_fix (fixS *fixP, valueT *valueP, segT seg ATTRIBUTE_UNUSED)
switch (fixP->fx_r_type)
{
case BFD_RELOC_BFIN_GOT:
+ case BFD_RELOC_BFIN_GOT17M4:
+ case BFD_RELOC_BFIN_FUNCDESC_GOT17M4:
fixP->fx_no_overflow = 1;
newval = md_chars_to_number (where, 2);
newval |= 0x0 & 0x7f;
@@ -579,6 +661,7 @@ md_apply_fix (fixS *fixP, valueT *valueP, segT seg ATTRIBUTE_UNUSED)
md_number_to_chars (where, value, 2);
break;
+ case BFD_RELOC_BFIN_FUNCDESC:
case BFD_RELOC_VTABLE_INHERIT:
case BFD_RELOC_VTABLE_ENTRY:
fixP->fx_done = FALSE;
@@ -725,8 +808,10 @@ bfin_fix_adjustable (fixS *fixP)
switch (fixP->fx_r_type)
{
/* Adjust_reloc_syms doesn't know about the GOT. */
- case BFD_RELOC_BFIN_GOT :
- case BFD_RELOC_BFIN_PLTPC :
+ case BFD_RELOC_BFIN_GOT:
+ case BFD_RELOC_BFIN_GOT17M4:
+ case BFD_RELOC_BFIN_FUNCDESC_GOT17M4:
+ case BFD_RELOC_BFIN_PLTPC:
/* We need the symbol name for the VTABLE entries. */
case BFD_RELOC_VTABLE_INHERIT:
case BFD_RELOC_VTABLE_ENTRY:
@@ -982,6 +1067,8 @@ Expr_Node_Gen_Reloc (Expr_Node * head, int parent_reloc)
break;
case BFD_RELOC_16:
case BFD_RELOC_BFIN_GOT:
+ case BFD_RELOC_BFIN_GOT17M4:
+ case BFD_RELOC_BFIN_FUNCDESC_GOT17M4:
note1 = conscode (gencode (value), NULL_CODE);
pcrel = 0;
break;
@@ -1356,8 +1443,6 @@ bfin_gen_ldimmhalf (REG_T reg, int H, int S, int Z, Expr_Node * phword, int relo
INSTR_T
bfin_gen_ldstidxi (REG_T ptr, REG_T reg, int W, int sz, int Z, Expr_Node * poffset)
{
- int offset;
- int value = 0;
INIT (LDSTidxI);
if (!IS_PREG (*ptr) || (!IS_DREG (*reg) && !Z))
@@ -1370,44 +1455,51 @@ bfin_gen_ldstidxi (REG_T ptr, REG_T reg, int W, int sz, int Z, Expr_Node * poffs
ASSIGN_R (reg);
ASSIGN (W);
ASSIGN (sz);
- switch (sz)
- {
- case 0:
- value = EXPR_VALUE (poffset) >> 2;
- break;
- case 1:
- value = EXPR_VALUE (poffset) >> 1;
- break;
- case 2:
- value = EXPR_VALUE (poffset);
- break;
- }
-
ASSIGN (Z);
- offset = (value & 0xffff);
- ASSIGN (offset);
- /* TODO : test if you need to check this here.
- The reloc case should automatically generate instruction
- if constant. */
- if(poffset->type != Expr_Node_Constant){
- /* A GOT relocation such as R0 = [P5 + symbol@GOT].
- Distinguish between R0 = [P5 + symbol@GOT] and
- P5 = [P5 + _current_shared_library_p5_offset_]. */
- if(!strcmp(poffset->value.s_value, "_current_shared_library_p5_offset_")){
- return conscode (gencode (HI (c_code.opcode)),
- Expr_Node_Gen_Reloc(poffset, BFD_RELOC_16));
+ if (poffset->type != Expr_Node_Constant)
+ {
+ /* a GOT relocation such as R0 = [P5 + symbol@GOT] */
+ /* distinguish between R0 = [P5 + symbol@GOT] and
+ P5 = [P5 + _current_shared_library_p5_offset_]
+ */
+ if (poffset->type == Expr_Node_Reloc
+ && !strcmp (poffset->value.s_value,
+ "_current_shared_library_p5_offset_"))
+ {
+ return conscode (gencode (HI (c_code.opcode)),
+ Expr_Node_Gen_Reloc(poffset, BFD_RELOC_16));
+ }
+ else if (poffset->type != Expr_Node_GOT_Reloc)
+ abort ();
+
+ return conscode (gencode (HI (c_code.opcode)),
+ Expr_Node_Gen_Reloc(poffset->Left_Child,
+ poffset->value.i_value));
}
- else
+ else
{
- return conscode (gencode (HI (c_code.opcode)),
- Expr_Node_Gen_Reloc(poffset, BFD_RELOC_BFIN_GOT));
+ int value, offset;
+ switch (sz)
+ { // load/store access size
+ case 0: // 32 bit
+ value = EXPR_VALUE (poffset) >> 2;
+ break;
+ case 1: // 16 bit
+ value = EXPR_VALUE (poffset) >> 1;
+ break;
+ case 2: // 8 bit
+ value = EXPR_VALUE (poffset);
+ break;
+ default:
+ abort ();
+ }
+
+ offset = (value & 0xffff);
+ ASSIGN (offset);
+ return GEN_OPCODE32 ();
}
- }
- else{
- return GEN_OPCODE32 ();
- }
}