/* tc-alpha.c - Processor-specific code for the DEC Alpha AXP CPU.
- Copyright 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
- Free Software Foundation, Inc.
+ Copyright 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+ 2001, 2002 Free Software Foundation, Inc.
Contributed by Carnegie Mellon University, 1993.
Written by Alessandro Forin, based on earlier gas-1.38 target CPU files.
Modified by Ken Raeburn for gas-2.x and ECOFF support.
#define O_gprelhigh O_md9 /* !gprelhigh relocation */
#define O_gprellow O_md10 /* !gprellow relocation */
#define O_gprel O_md11 /* !gprel relocation */
+#define O_samegp O_md12 /* !samegp relocation */
#define DUMMY_RELOC_LITUSE_ADDR (BFD_RELOC_UNUSED + 1)
#define DUMMY_RELOC_LITUSE_BASE (BFD_RELOC_UNUSED + 2)
#define LITUSE_BYTOFF 2
#define LITUSE_JSR 3
-#define USER_RELOC_P(R) ((R) >= O_literal && (R) <= O_gprel)
+#define USER_RELOC_P(R) ((R) >= O_literal && (R) <= O_samegp)
/* Macros for extracting the type and number of encoded register tokens */
DEF(gpdisp, BFD_RELOC_ALPHA_GPDISP, 1, 1),
DEF(gprelhigh, BFD_RELOC_ALPHA_GPREL_HI16, 0, 0),
DEF(gprellow, BFD_RELOC_ALPHA_GPREL_LO16, 0, 0),
- DEF(gprel, BFD_RELOC_GPREL16, 0, 0)
+ DEF(gprel, BFD_RELOC_GPREL16, 0, 0),
+ DEF(samegp, BFD_RELOC_ALPHA_BRSGP, 0, 0)
};
#undef DEF
}
return;
+#ifdef OBJ_ELF
+ case BFD_RELOC_ALPHA_BRSGP:
+ return;
+#endif
+
#ifdef OBJ_ECOFF
case BFD_RELOC_ALPHA_LITERAL:
md_number_to_chars (fixpos, value, 2);
alpha_insn_label = sym;
}
+/* If we have a BRSGP reloc to a local symbol, adjust it to BRADDR and
+ let it get resolved at assembly time. */
+
+void
+alpha_validate_fix (f)
+ fixS *f;
+{
+#ifdef OBJ_ELF
+ int offset = 0;
+ const char *name;
+
+ if (f->fx_r_type != BFD_RELOC_ALPHA_BRSGP)
+ return;
+
+ if (! S_IS_DEFINED (f->fx_addsy))
+ return;
+
+ switch (S_GET_OTHER (f->fx_addsy) & STO_ALPHA_STD_GPLOAD)
+ {
+ case STO_ALPHA_NOPV:
+ break;
+ case STO_ALPHA_STD_GPLOAD:
+ offset = 8;
+ break;
+ default:
+ if (S_IS_LOCAL (f->fx_addsy))
+ name = "<local>";
+ else
+ name = S_GET_NAME (f->fx_addsy);
+ as_bad_where (f->fx_file, f->fx_line,
+ _("!samegp reloc against symbol without .prologue: %s"),
+ name);
+ break;
+ }
+
+ if (! (S_IS_EXTERN (f->fx_addsy) || S_IS_WEAK (f->fx_addsy)))
+ {
+ f->fx_r_type = BFD_RELOC_23_PCREL_S2;
+ f->fx_offset += offset;
+ }
+#endif
+}
+
/* Return true if we must always emit a reloc for a type and false if
there is some hope of resolving it at assembly time. */
case BFD_RELOC_ALPHA_GPREL_LO16:
case BFD_RELOC_ALPHA_LINKAGE:
case BFD_RELOC_ALPHA_CODEADDR:
+ case BFD_RELOC_ALPHA_BRSGP:
case BFD_RELOC_VTABLE_INHERIT:
case BFD_RELOC_VTABLE_ENTRY:
return 1;
return 0;
default:
- assert ((int) f->fx_r_type < 0
- && -(int) f->fx_r_type < (int) alpha_num_operands);
return 0;
}
}
case BFD_RELOC_ALPHA_GPDISP_HI16:
case BFD_RELOC_ALPHA_GPDISP_LO16:
case BFD_RELOC_ALPHA_GPDISP:
+ case BFD_RELOC_ALPHA_BRSGP:
return 0;
case BFD_RELOC_ALPHA_LITERAL:
return 1;
default:
- assert ((int) f->fx_r_type < 0
- && - (int) f->fx_r_type < (int) alpha_num_operands);
return 1;
}
/*NOTREACHED*/
* of thing, and as a result we need to fake it out here.
*/
if ((S_IS_EXTERN (fixp->fx_addsy) || S_IS_WEAK (fixp->fx_addsy)
- || (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_MERGE))
+ || (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_MERGE)
+ || (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_THREAD_LOCAL))
&& !S_IS_COMMON (fixp->fx_addsy))
reloc->addend -= symbol_get_bfdsym (fixp->fx_addsy)->value;
#endif
case O_pregister: name = "O_pregister"; break;
case O_cpregister: name = "O_cpregister"; break;
case O_literal: name = "O_literal"; break;
+ case O_lituse_addr: name = "O_lituse_addr"; break;
case O_lituse_base: name = "O_lituse_base"; break;
case O_lituse_bytoff: name = "O_lituse_bytoff"; break;
case O_lituse_jsr: name = "O_lituse_jsr"; break;
case O_gprelhigh: name = "O_gprelhigh"; break;
case O_gprellow: name = "O_gprellow"; break;
case O_gprel: name = "O_gprel"; break;
- case O_md11: name = "O_md11"; break;
- case O_md12: name = "O_md12"; break;
+ case O_samegp: name = "O_samegp"; break;
case O_md13: name = "O_md13"; break;
case O_md14: name = "O_md14"; break;
case O_md15: name = "O_md15"; break;
goto err;
++input_line_pointer;
- SKIP_WHITESPACE ();
+ SKIP_WHITESPACE ();
p = input_line_pointer;
c = get_symbol_end ();
}
*input_line_pointer = c;
- SKIP_WHITESPACE ();
+ SKIP_WHITESPACE ();
if (*input_line_pointer != '!')
{
if (r->require_seq)
case O_gprelhigh:
case O_gprellow:
case O_gprel:
+ case O_samegp:
goto match_failed;
default:
abort ();
/* There is one special case for which an insn receives two
- relocations, and thus the user-supplied reloc does not
+ relocations, and thus the user-supplied reloc does not
override the operand reloc. */
if (operand->default_reloc == BFD_RELOC_ALPHA_HINT)
{
int cpumatch = 1;
bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
+#ifdef RELOC_OP_P
/* If a user-specified relocation is present, this is not a macro. */
if (ntok && USER_RELOC_P (tok[ntok - 1].X_op))
{
reloc = ALPHA_RELOC_TABLE (tok[ntok - 1].X_op)->reloc;
ntok--;
}
- else if (local_macros_on)
+ else
+#endif
+ if (local_macros_on)
{
macro = ((const struct alpha_macro *)
hash_find (alpha_macro_hash, opname));
int i;
{
+#ifdef OBJ_ELF
+ obj_elf_text (i);
+#else
s_text (i);
+#endif
alpha_insn_label = NULL;
alpha_auto_align_on = 1;
alpha_current_align = 0;
s_alpha_data (i)
int i;
{
+#ifdef OBJ_ELF
+ obj_elf_data (i);
+#else
s_data (i);
+#endif
alpha_insn_label = NULL;
alpha_auto_align_on = 1;
alpha_current_align = 0;
if (letter == 's')
return SHF_ALPHA_GPREL;
- *ptr_msg = _("Bad .section directive: want a,s,w,x,M,S in string");
+ *ptr_msg = _("Bad .section directive: want a,s,w,x,M,S,G,T in string");
return 0;
}