/* tc-sparc.c -- Assemble for the SPARC
Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
GAS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
+ the Free Software Foundation; either version 3, or (at your option)
any later version.
GAS is distributed in the hope that it will be useful,
You should have received a copy of the GNU General Public
License along with GAS; see the file COPYING. If not, write
- to the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-#include <stdio.h>
+ to the Free Software Foundation, 51 Franklin Street - Fifth Floor,
+ Boston, MA 02110-1301, USA. */
#include "as.h"
#include "safe-ctype.h"
#define U0xffffffff ((((unsigned long) 1 << 16) << 16) - 1)
#define U0x80000000 ((((unsigned long) 1 << 16) << 15))
-static struct sparc_arch *lookup_arch PARAMS ((char *));
-static void init_default_arch PARAMS ((void));
-static int sparc_ip PARAMS ((char *, const struct sparc_opcode **));
-static int in_signed_range PARAMS ((bfd_signed_vma, bfd_signed_vma));
-static int in_unsigned_range PARAMS ((bfd_vma, bfd_vma));
-static int in_bitfield_range PARAMS ((bfd_signed_vma, bfd_signed_vma));
-static int sparc_ffs PARAMS ((unsigned int));
-static void synthetize_setuw PARAMS ((const struct sparc_opcode *));
-static void synthetize_setsw PARAMS ((const struct sparc_opcode *));
-static void synthetize_setx PARAMS ((const struct sparc_opcode *));
-static bfd_vma BSR PARAMS ((bfd_vma, int));
-static int cmp_reg_entry PARAMS ((const PTR, const PTR));
-static int parse_keyword_arg PARAMS ((int (*) (const char *), char **, int *));
-static int parse_const_expr_arg PARAMS ((char **, int *));
-static int get_expression PARAMS ((char *str));
+static int sparc_ip (char *, const struct sparc_opcode **);
+static int parse_keyword_arg (int (*) (const char *), char **, int *);
+static int parse_const_expr_arg (char **, int *);
+static int get_expression (char *);
/* Default architecture. */
/* ??? The default value should be V8, but sparclite support was added
/* Handle of the OPCODE hash table. */
static struct hash_control *op_hash;
-static int log2 PARAMS ((int));
-static void s_data1 PARAMS ((void));
-static void s_seg PARAMS ((int));
-static void s_proc PARAMS ((int));
-static void s_reserve PARAMS ((int));
-static void s_common PARAMS ((int));
-static void s_empty PARAMS ((int));
-static void s_uacons PARAMS ((int));
-static void s_ncons PARAMS ((int));
+static void s_data1 (void);
+static void s_seg (int);
+static void s_proc (int);
+static void s_reserve (int);
+static void s_common (int);
+static void s_empty (int);
+static void s_uacons (int);
+static void s_ncons (int);
#ifdef OBJ_ELF
-static void s_register PARAMS ((int));
+static void s_register (int);
#endif
const pseudo_typeS md_pseudo_table[] =
{NULL, 0, 0},
};
-/* Size of relocation record. */
-const int md_reloc_size = 12;
-
/* This array holds the chars that always start a comment. If the
pre-processor is disabled, these aren't very useful. */
const char comment_chars[] = "!"; /* JF removed '|' from
changed in read.c. Ideally it shouldn't have to know about it at all,
but nothing is ideal around here. */
-#define isoctal(c) ((unsigned) ((c) - '0') < '8')
+#define isoctal(c) ((unsigned) ((c) - '0') < 8)
struct sparc_it
{
struct sparc_it the_insn, set_insn;
-static void output_insn
- PARAMS ((const struct sparc_opcode *, struct sparc_it *));
+static void output_insn (const struct sparc_opcode *, struct sparc_it *);
\f
/* Table of arguments to -A.
The sparc_opcode_arch table in sparc-opc.c is insufficient and incorrect
static enum sparc_arch_types default_arch_type;
static struct sparc_arch *
-lookup_arch (name)
- char *name;
+lookup_arch (char *name)
{
struct sparc_arch *sa;
architecture name. */
static void
-init_default_arch ()
+init_default_arch (void)
{
struct sparc_arch *sa = lookup_arch (default_arch);
/* Called by TARGET_FORMAT. */
const char *
-sparc_target_format ()
+sparc_target_format (void)
{
/* We don't get a chance to initialize anything before we're called,
so handle that now. */
#endif
#endif
+#ifdef TE_VXWORKS
+ return "elf32-sparc-vxworks";
+#endif
+
#ifdef OBJ_ELF
- return sparc_arch_size == 64 ? "elf64-sparc" : "elf32-sparc";
+ return sparc_arch_size == 64 ? ELF64_TARGET_FORMAT : ELF_TARGET_FORMAT;
#endif
abort ();
size_t md_longopts_size = sizeof (md_longopts);
int
-md_parse_option (c, arg)
- int c;
- char *arg;
+md_parse_option (int c, char *arg)
{
/* We don't get a chance to initialize anything before we're called,
so handle that now. */
{
if (sparc_arch_size == 32)
{
- if (strcmp (*l, "elf32-sparc") == 0)
+ if (CONST_STRNEQ (*l, "elf32-sparc"))
break;
}
else
{
- if (strcmp (*l, "elf64-sparc") == 0)
+ if (CONST_STRNEQ (*l, "elf64-sparc"))
break;
}
}
}
void
-md_show_usage (stream)
- FILE *stream;
+md_show_usage (FILE *stream)
{
const struct sparc_arch *arch;
int column;
{NULL, NULL, NULL},
};
\f
-/* sparc64 privileged registers. */
+/* sparc64 privileged and hyperprivileged registers. */
struct priv_reg_entry
{
{"otherwin", 13},
{"wstate", 14},
{"fq", 15},
+ {"gl", 16},
{"ver", 31},
{"", -1}, /* End marker. */
};
-/* v9a specific asrs. */
+struct priv_reg_entry hpriv_reg_table[] =
+{
+ {"hpstate", 0},
+ {"htstate", 1},
+ {"hintp", 3},
+ {"htba", 5},
+ {"hver", 6},
+ {"hstick_cmpr", 31},
+ {"", -1}, /* End marker. */
+};
+
+/* v9a specific asrs. This table is ordered by initial
+ letter, in reverse. */
struct priv_reg_entry v9a_asr_table[] =
{
{"tick_cmpr", 23},
{"sys_tick_cmpr", 25},
{"sys_tick", 24},
+ {"stick_cmpr", 25},
+ {"stick", 24},
+ {"softint_clear", 21},
+ {"softint_set", 20},
{"softint", 22},
{"set_softint", 20},
{"pic", 17},
};
static int
-cmp_reg_entry (parg, qarg)
- const PTR parg;
- const PTR qarg;
+cmp_reg_entry (const void *parg, const void *qarg)
{
const struct priv_reg_entry *p = (const struct priv_reg_entry *) parg;
const struct priv_reg_entry *q = (const struct priv_reg_entry *) qarg;
need. */
void
-md_begin ()
+md_begin (void)
{
register const char *retval = NULL;
int lose = 0;
while (i < (unsigned int) sparc_num_opcodes)
{
const char *name = sparc_opcodes[i].name;
- retval = hash_insert (op_hash, name, (PTR) &sparc_opcodes[i]);
+ retval = hash_insert (op_hash, name, (void *) &sparc_opcodes[i]);
if (retval != NULL)
{
as_bad (_("Internal error: can't hash `%s': %s\n"),
}
else
{
- retval = hash_insert (op_hash, native_op_table[i].name, (PTR) insn);
+ retval = hash_insert (op_hash, native_op_table[i].name,
+ (void *) insn);
if (retval != NULL)
{
as_bad (_("Internal error: can't hash `%s': %s\n"),
/* Called after all assembly has been done. */
void
-sparc_md_end ()
+sparc_md_end (void)
{
unsigned long mach = bfd_mach_sparc;
\f
/* Return non-zero if VAL is in the range -(MAX+1) to MAX. */
-static INLINE int
-in_signed_range (val, max)
- bfd_signed_vma val, max;
+static inline int
+in_signed_range (bfd_signed_vma val, bfd_signed_vma max)
{
if (max <= 0)
abort ();
/* Return non-zero if VAL is in the range 0 to MAX. */
-static INLINE int
-in_unsigned_range (val, max)
- bfd_vma val, max;
+static inline int
+in_unsigned_range (bfd_vma val, bfd_vma max)
{
if (val > max)
return 0;
/* Return non-zero if VAL is in the range -(MAX/2+1) to MAX.
(e.g. -15 to +31). */
-static INLINE int
-in_bitfield_range (val, max)
- bfd_signed_vma val, max;
+static inline int
+in_bitfield_range (bfd_signed_vma val, bfd_signed_vma max)
{
if (max <= 0)
abort ();
}
static int
-sparc_ffs (mask)
- unsigned int mask;
+sparc_ffs (unsigned int mask)
{
int i;
/* Implement big shift right. */
static bfd_vma
-BSR (val, amount)
- bfd_vma val;
- int amount;
+BSR (bfd_vma val, int amount)
{
if (sizeof (bfd_vma) <= 4 && amount >= 32)
as_fatal (_("Support for 64-bit arithmetic not compiled in."));
/* Handle the set and setuw synthetic instructions. */
static void
-synthetize_setuw (insn)
- const struct sparc_opcode *insn;
+synthetize_setuw (const struct sparc_opcode *insn)
{
int need_hi22_p = 0;
int rd = (the_insn.opcode & RD (~0)) >> 25;
/* Handle the setsw synthetic instruction. */
static void
-synthetize_setsw (insn)
- const struct sparc_opcode *insn;
+synthetize_setsw (const struct sparc_opcode *insn)
{
int low32, rd, opc;
/* Handle the setsw synthetic instruction. */
static void
-synthetize_setx (insn)
- const struct sparc_opcode *insn;
+synthetize_setx (const struct sparc_opcode *insn)
{
int upper32, lower32;
int tmpreg = (the_insn.opcode & RS1 (~0)) >> 14;
/* Main entry point to assemble one instruction. */
void
-md_assemble (str)
- char *str;
+md_assemble (char *str)
{
const struct sparc_opcode *insn;
int special_case;
know (str);
special_case = sparc_ip (str, &insn);
+ if (insn == NULL)
+ return;
/* We warn about attempts to put a floating point branch in a delay slot,
unless the delay slot has been annulled. */
- if (insn != NULL
- && last_insn != NULL
+ if (last_insn != NULL
&& (insn->flags & F_FBR) != 0
&& (last_insn->flags & F_DELAYED) != 0
/* ??? This test isn't completely accurate. We assume anything with
point instruction and a floating point branch. We insert one
automatically, with a warning. */
if (max_architecture < SPARC_OPCODE_ARCH_V9
- && insn != NULL
&& last_insn != NULL
&& (insn->flags & F_FBR) != 0
&& (last_insn->flags & F_FLOAT) != 0)
/* Subroutine of md_assemble to do the actual parsing. */
static int
-sparc_ip (str, pinsn)
- char *str;
- const struct sparc_opcode **pinsn;
+sparc_ip (char *str, const struct sparc_opcode **pinsn)
{
char *error_message = "";
char *s;
break;
default:
- as_fatal (_("Unknown opcode: `%s'"), str);
+ as_bad (_("Unknown opcode: `%s'"), str);
+ *pinsn = NULL;
+ return special_case;
}
insn = (struct sparc_opcode *) hash_find (op_hash, str);
*pinsn = insn;
goto error;
}
+ case '$':
+ case '%':
+ /* Parse a sparc64 hyperprivileged register. */
+ if (*s == '%')
+ {
+ struct priv_reg_entry *p = hpriv_reg_table;
+ unsigned int len = 9999999; /* Init to make gcc happy. */
+
+ s += 1;
+ while (p->name[0] > s[0])
+ p++;
+ while (p->name[0] == s[0])
+ {
+ len = strlen (p->name);
+ if (strncmp (p->name, s, len) == 0)
+ break;
+ p++;
+ }
+ if (p->name[0] != s[0])
+ {
+ error_message = _(": unrecognizable hyperprivileged register");
+ goto error;
+ }
+ if (*args == '$')
+ opcode |= (p->regnum << 14);
+ else
+ opcode |= (p->regnum << 25);
+ s += len;
+ continue;
+ }
+ else
+ {
+ error_message = _(": unrecognizable hyperprivileged register");
+ goto error;
+ }
+
case '_':
case '/':
/* Parse a v9a/v9b ancillary state register. */
case '\0': /* End of args. */
if (s[0] == ',' && s[1] == '%')
{
- static const struct tls_ops {
+ static const struct ops
+ {
/* The name as it appears in assembler. */
char *name;
/* strlen (name), precomputed for speed */
int len;
/* The reloc this pseudo-op translates to. */
int reloc;
- /* 1 if call. */
- int call;
- } tls_ops[] = {
+ /* 1 if tls call. */
+ int tls_call;
+ }
+ ops[] =
+ {
{ "tgd_add", 7, BFD_RELOC_SPARC_TLS_GD_ADD, 0 },
{ "tgd_call", 8, BFD_RELOC_SPARC_TLS_GD_CALL, 1 },
{ "tldm_add", 8, BFD_RELOC_SPARC_TLS_LDM_ADD, 0 },
{ "tldo_add", 8, BFD_RELOC_SPARC_TLS_LDO_ADD, 0 },
{ "tie_ldx", 7, BFD_RELOC_SPARC_TLS_IE_LDX, 0 },
{ "tie_ld", 6, BFD_RELOC_SPARC_TLS_IE_LD, 0 },
- { "tie_add", 7, BFD_RELOC_SPARC_TLS_IE_ADD, 0 }
+ { "tie_add", 7, BFD_RELOC_SPARC_TLS_IE_ADD, 0 },
+ { "gdop", 4, BFD_RELOC_SPARC_GOTDATA_OP, 0 },
+ { NULL, 0, 0, 0 }
};
- const struct tls_ops *o;
+ const struct ops *o;
char *s1;
int npar = 0;
- for (o = tls_ops; o->name; o++)
+ for (o = ops; o->name; o++)
if (strncmp (s + 2, o->name, o->len) == 0)
break;
if (o->name == NULL)
return special_case;
}
- if (! o->call && the_insn.reloc != BFD_RELOC_NONE)
+ if (! o->tls_call && the_insn.reloc != BFD_RELOC_NONE)
{
as_bad (_("Illegal operands: %%%s cannot be used together with other relocs in the insn ()"),
o->name);
return special_case;
}
- if (o->call
+ if (o->tls_call
&& (the_insn.reloc != BFD_RELOC_32_PCREL_S2
|| the_insn.exp.X_add_number != 0
|| the_insn.exp.X_add_symbol
{
if (SPARC_OPCODE_ARCH_V9_P (max_architecture))
{
+ if (*args == 'e' || *args == 'f' || *args == 'g')
+ {
+ error_message
+ = _(": There are only 32 single precision f registers; [0-31]");
+ goto error;
+ }
v9_arg_p = 1;
mask -= 31; /* wrap high bit */
}
{
char *s1;
char *op_arg = NULL;
- expressionS op_exp;
+ static expressionS op_exp;
bfd_reloc_code_real_type old_reloc = the_insn.reloc;
/* Check for %hi, etc. */
{ "lox", 3, BFD_RELOC_SPARC_LOX10, 1, 0 },
{ "hi", 2, BFD_RELOC_HI22, 0, 1 },
{ "lo", 2, BFD_RELOC_LO10, 0, 1 },
+ { "pc22", 4, BFD_RELOC_SPARC_PC22, 0, 1 },
+ { "pc10", 4, BFD_RELOC_SPARC_PC10, 0, 1 },
{ "hh", 2, BFD_RELOC_SPARC_HH22, 1, 1 },
{ "hm", 2, BFD_RELOC_SPARC_HM10, 1, 1 },
{ "lm", 2, BFD_RELOC_SPARC_LM22, 1, 1 },
{ "tie_lo10", 8, BFD_RELOC_SPARC_TLS_IE_LO10, 0, 0 },
{ "tle_hix22", 9, BFD_RELOC_SPARC_TLS_LE_HIX22, 0, 0 },
{ "tle_lox10", 9, BFD_RELOC_SPARC_TLS_LE_LOX10, 0, 0 },
+ { "gdop_hix22", 10, BFD_RELOC_SPARC_GOTDATA_OP_HIX22,
+ 0, 0 },
+ { "gdop_lox10", 10, BFD_RELOC_SPARC_GOTDATA_OP_LOX10,
+ 0, 0 },
{ NULL, 0, 0, 0, 0 }
};
const struct ops *o;
goto error;
}
- /* Constants that won't fit are checked in md_apply_fix3
+ /* Constants that won't fit are checked in md_apply_fix
and bfd_install_relocation.
??? It would be preferable to install the constants
into the insn here and save having to create a fixS
for each one. There already exists code to handle
- all the various cases (e.g. in md_apply_fix3 and
+ all the various cases (e.g. in md_apply_fix and
bfd_install_relocation) so duplicating all that code
here isn't right. */
}
If successful, INPUT_POINTER is updated. */
static int
-parse_keyword_arg (lookup_fn, input_pointerP, valueP)
- int (*lookup_fn) PARAMS ((const char *));
- char **input_pointerP;
- int *valueP;
+parse_keyword_arg (int (*lookup_fn) (const char *),
+ char **input_pointerP,
+ int *valueP)
{
int value;
char c, *p, *q;
The result is a boolean indicating success. */
static int
-parse_const_expr_arg (input_pointerP, valueP)
- char **input_pointerP;
- int *valueP;
+parse_const_expr_arg (char **input_pointerP, int *valueP)
{
char *save = input_line_pointer;
expressionS exp;
/* Subroutine of sparc_ip to parse an expression. */
static int
-get_expression (str)
- char *str;
+get_expression (char *str)
{
char *save_in;
segT seg;
/* Subroutine of md_assemble to output one insn. */
static void
-output_insn (insn, the_insn)
- const struct sparc_opcode *insn;
- struct sparc_it *the_insn;
+output_insn (const struct sparc_opcode *insn, struct sparc_it *the_insn)
{
char *toP = frag_more (4);
the_insn->pcrel,
the_insn->reloc);
/* Turn off overflow checking in fixup_segment. We'll do our
- own overflow checking in md_apply_fix3. This is necessary because
+ own overflow checking in md_apply_fix. This is necessary because
the insn size is 4 and fixup_segment will signal an overflow for
large 8 byte quantities. */
fixP->fx_no_overflow = 1;
#endif
}
\f
-/* This is identical to the md_atof in m68k.c. I think this is right,
- but I'm not sure.
-
- Turn a string in input_line_pointer into a floating point constant
- of type TYPE, and store the appropriate bytes in *LITP. The number
- of LITTLENUMS emitted is stored in *SIZEP. An error message is
- returned, or NULL on OK. */
-
-/* Equal to MAX_PRECISION in atof-ieee.c. */
-#define MAX_LITTLENUMS 6
-
char *
-md_atof (type, litP, sizeP)
- char type;
- char *litP;
- int *sizeP;
+md_atof (int type, char *litP, int *sizeP)
{
- int i, prec;
- LITTLENUM_TYPE words[MAX_LITTLENUMS];
- char *t;
-
- switch (type)
- {
- case 'f':
- case 'F':
- case 's':
- case 'S':
- prec = 2;
- break;
-
- case 'd':
- case 'D':
- case 'r':
- case 'R':
- prec = 4;
- break;
-
- case 'x':
- case 'X':
- prec = 6;
- break;
-
- case 'p':
- case 'P':
- prec = 6;
- break;
-
- default:
- *sizeP = 0;
- return _("Bad call to MD_ATOF()");
- }
-
- t = atof_ieee (input_line_pointer, type, words);
- if (t)
- input_line_pointer = t;
- *sizeP = prec * sizeof (LITTLENUM_TYPE);
-
- if (target_big_endian)
- {
- for (i = 0; i < prec; i++)
- {
- md_number_to_chars (litP, (valueT) words[i],
- sizeof (LITTLENUM_TYPE));
- litP += sizeof (LITTLENUM_TYPE);
- }
- }
- else
- {
- for (i = prec - 1; i >= 0; i--)
- {
- md_number_to_chars (litP, (valueT) words[i],
- sizeof (LITTLENUM_TYPE));
- litP += sizeof (LITTLENUM_TYPE);
- }
- }
-
- return 0;
+ return ieee_md_atof (type, litP, sizeP, target_big_endian);
}
/* Write a value out to the object file, using the appropriate
endianness. */
void
-md_number_to_chars (buf, val, n)
- char *buf;
- valueT val;
- int n;
+md_number_to_chars (char *buf, valueT val, int n)
{
if (target_big_endian)
number_to_chars_bigendian (buf, val, n);
hold. */
void
-md_apply_fix3 (fixP, valP, segment)
- fixS *fixP;
- valueT *valP;
- segT segment ATTRIBUTE_UNUSED;
+md_apply_fix (fixS *fixP, valueT *valP, segT segment ATTRIBUTE_UNUSED)
{
char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
offsetT val = * (offsetT *) valP;
#ifdef OBJ_ELF
/* SPARC ELF relocations don't use an addend in the data field. */
if (fixP->fx_addsy != NULL)
- return;
+ {
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_SPARC_TLS_GD_HI22:
+ case BFD_RELOC_SPARC_TLS_GD_LO10:
+ case BFD_RELOC_SPARC_TLS_GD_ADD:
+ case BFD_RELOC_SPARC_TLS_GD_CALL:
+ case BFD_RELOC_SPARC_TLS_LDM_HI22:
+ case BFD_RELOC_SPARC_TLS_LDM_LO10:
+ case BFD_RELOC_SPARC_TLS_LDM_ADD:
+ case BFD_RELOC_SPARC_TLS_LDM_CALL:
+ case BFD_RELOC_SPARC_TLS_LDO_HIX22:
+ case BFD_RELOC_SPARC_TLS_LDO_LOX10:
+ case BFD_RELOC_SPARC_TLS_LDO_ADD:
+ case BFD_RELOC_SPARC_TLS_IE_HI22:
+ case BFD_RELOC_SPARC_TLS_IE_LO10:
+ case BFD_RELOC_SPARC_TLS_IE_LD:
+ case BFD_RELOC_SPARC_TLS_IE_LDX:
+ case BFD_RELOC_SPARC_TLS_IE_ADD:
+ case BFD_RELOC_SPARC_TLS_LE_HIX22:
+ case BFD_RELOC_SPARC_TLS_LE_LOX10:
+ case BFD_RELOC_SPARC_TLS_DTPMOD32:
+ case BFD_RELOC_SPARC_TLS_DTPMOD64:
+ case BFD_RELOC_SPARC_TLS_DTPOFF32:
+ case BFD_RELOC_SPARC_TLS_DTPOFF64:
+ case BFD_RELOC_SPARC_TLS_TPOFF32:
+ case BFD_RELOC_SPARC_TLS_TPOFF64:
+ S_SET_THREAD_LOCAL (fixP->fx_addsy);
+
+ default:
+ break;
+ }
+
+ return;
+ }
#endif
/* This is a hack. There should be a better way to
break;
case BFD_RELOC_SPARC_WDISP16:
- /* FIXME: simplify. */
- if (((val > 0) && (val & ~0x3fffc))
- || ((val < 0) && (~(val - 1) & ~0x3fffc)))
+ if ((val & 3)
+ || val >= 0x1fffc
+ || val <= -(offsetT) 0x20008)
as_bad_where (fixP->fx_file, fixP->fx_line,
_("relocation overflow"));
/* FIXME: The +1 deserves a comment. */
break;
case BFD_RELOC_SPARC_WDISP19:
- /* FIXME: simplify. */
- if (((val > 0) && (val & ~0x1ffffc))
- || ((val < 0) && (~(val - 1) & ~0x1ffffc)))
+ if ((val & 3)
+ || val >= 0xffffc
+ || val <= -(offsetT) 0x100008)
as_bad_where (fixP->fx_file, fixP->fx_line,
_("relocation overflow"));
/* FIXME: The +1 deserves a comment. */
format. */
arelent **
-tc_gen_reloc (section, fixp)
- asection *section ATTRIBUTE_UNUSED;
- fixS *fixp;
+tc_gen_reloc (asection *section, fixS *fixp)
{
static arelent *relocs[3];
arelent *reloc;
case BFD_RELOC_32_PCREL_S2:
case BFD_RELOC_SPARC13:
case BFD_RELOC_SPARC22:
+ case BFD_RELOC_SPARC_PC22:
+ case BFD_RELOC_SPARC_PC10:
case BFD_RELOC_SPARC_BASE13:
case BFD_RELOC_SPARC_WDISP16:
case BFD_RELOC_SPARC_WDISP19:
case BFD_RELOC_SPARC_TLS_LE_LOX10:
case BFD_RELOC_SPARC_TLS_DTPOFF32:
case BFD_RELOC_SPARC_TLS_DTPOFF64:
+ case BFD_RELOC_SPARC_GOTDATA_OP_HIX22:
+ case BFD_RELOC_SPARC_GOTDATA_OP_LOX10:
+ case BFD_RELOC_SPARC_GOTDATA_OP:
code = fixp->fx_r_type;
break;
default:
#define GOT_NAME "_GLOBAL_OFFSET_TABLE_"
#else
#define GOT_NAME "__GLOBAL_OFFSET_TABLE_"
+#endif
+#ifdef TE_VXWORKS
+#define GOTT_BASE "__GOTT_BASE__"
+#define GOTT_INDEX "__GOTT_INDEX__"
#endif
/* This code must be parallel to the OBJ_ELF tc_fix_adjustable. */
code = BFD_RELOC_SPARC_WPLT30;
break;
case BFD_RELOC_HI22:
- if (fixp->fx_addsy != NULL
- && strcmp (S_GET_NAME (fixp->fx_addsy), GOT_NAME) == 0)
- code = BFD_RELOC_SPARC_PC22;
- else
- code = BFD_RELOC_SPARC_GOT22;
+ code = BFD_RELOC_SPARC_GOT22;
+ if (fixp->fx_addsy != NULL)
+ {
+ if (strcmp (S_GET_NAME (fixp->fx_addsy), GOT_NAME) == 0)
+ code = BFD_RELOC_SPARC_PC22;
+#ifdef TE_VXWORKS
+ if (strcmp (S_GET_NAME (fixp->fx_addsy), GOTT_BASE) == 0
+ || strcmp (S_GET_NAME (fixp->fx_addsy), GOTT_INDEX) == 0)
+ code = BFD_RELOC_HI22; /* Unchanged. */
+#endif
+ }
break;
case BFD_RELOC_LO10:
- if (fixp->fx_addsy != NULL
- && strcmp (S_GET_NAME (fixp->fx_addsy), GOT_NAME) == 0)
- code = BFD_RELOC_SPARC_PC10;
- else
- code = BFD_RELOC_SPARC_GOT10;
+ code = BFD_RELOC_SPARC_GOT10;
+ if (fixp->fx_addsy != NULL)
+ {
+ if (strcmp (S_GET_NAME (fixp->fx_addsy), GOT_NAME) == 0)
+ code = BFD_RELOC_SPARC_PC10;
+#ifdef TE_VXWORKS
+ if (strcmp (S_GET_NAME (fixp->fx_addsy), GOTT_BASE) == 0
+ || strcmp (S_GET_NAME (fixp->fx_addsy), GOTT_INDEX) == 0)
+ code = BFD_RELOC_LO10; /* Unchanged. */
+#endif
+ }
break;
case BFD_RELOC_SPARC13:
code = BFD_RELOC_SPARC_GOT13;
}
#endif /* defined (OBJ_ELF) || defined (OBJ_AOUT) */
+ /* Nothing is aligned in DWARF debugging sections. */
+ if (bfd_get_section_flags (stdoutput, section) & SEC_DEBUGGING)
+ switch (code)
+ {
+ case BFD_RELOC_16: code = BFD_RELOC_SPARC_UA16; break;
+ case BFD_RELOC_32: code = BFD_RELOC_SPARC_UA32; break;
+ case BFD_RELOC_64: code = BFD_RELOC_SPARC_UA64; break;
+ default: break;
+ }
+
if (code == BFD_RELOC_SPARC_OLO10)
reloc->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO10);
else
/* We have no need to default values of symbols. */
symbolS *
-md_undefined_symbol (name)
- char *name ATTRIBUTE_UNUSED;
+md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
{
return 0;
}
/* Round up a section size to the appropriate boundary. */
valueT
-md_section_align (segment, size)
- segT segment ATTRIBUTE_UNUSED;
- valueT size;
+md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
{
#ifndef OBJ_ELF
/* This is not right for ELF; a.out wants it, and COFF will force
its size. This gets us to the following instruction.
(??? Is this right? FIXME-SOON) */
long
-md_pcrel_from (fixP)
- fixS *fixP;
+md_pcrel_from (fixS *fixP)
{
long ret;
of two. */
static int
-log2 (value)
- int value;
+mylog2 (int value)
{
int shift;
#endif
static void
-s_reserve (ignore)
- int ignore ATTRIBUTE_UNUSED;
+s_reserve (int ignore ATTRIBUTE_UNUSED)
{
char *name;
char *p;
if (align != 0)
{
- temp = log2 (align);
+ temp = mylog2 (align);
if (temp < 0)
{
as_bad (_("alignment not a power of 2"));
}
static void
-s_common (ignore)
- int ignore ATTRIBUTE_UNUSED;
+s_common (int ignore ATTRIBUTE_UNUSED)
{
char *name;
char c;
if (temp > max_alignment)
{
temp = max_alignment;
- as_warn (_("alignment too large; assuming %d"), temp);
+ as_warn (_("alignment too large; assuming %ld"), (long) temp);
}
#endif
if (temp == 0)
align = 0;
else
- align = log2 (temp);
+ align = mylog2 (temp);
if (align < 0)
{
goto allocate_common;
}
-#ifdef BFD_ASSEMBLER
symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
-#endif
demand_empty_rest_of_line ();
return;
invalid delay slot usage. */
static void
-s_empty (ignore)
- int ignore ATTRIBUTE_UNUSED;
+s_empty (int ignore ATTRIBUTE_UNUSED)
{
/* The easy way to implement is to just forget about the last
instruction. */
}
static void
-s_seg (ignore)
- int ignore ATTRIBUTE_UNUSED;
+s_seg (int ignore ATTRIBUTE_UNUSED)
{
if (strncmp (input_line_pointer, "\"text\"", 6) == 0)
}
static void
-s_data1 ()
+s_data1 (void)
{
subseg_set (data_section, 1);
demand_empty_rest_of_line ();
}
static void
-s_proc (ignore)
- int ignore ATTRIBUTE_UNUSED;
+s_proc (int ignore ATTRIBUTE_UNUSED)
{
while (!is_end_of_line[(unsigned char) *input_line_pointer])
{
to be aligned. */
static void
-s_uacons (bytes)
- int bytes;
+s_uacons (int bytes)
{
/* Tell sparc_cons_align not to align this value. */
sparc_no_align_cons = 1;
sparc_arch_size 64 it is equivalent to .xword. */
static void
-s_ncons (bytes)
- int bytes ATTRIBUTE_UNUSED;
+s_ncons (int bytes ATTRIBUTE_UNUSED)
{
cons (sparc_arch_size == 32 ? 4 : 8);
}
*/
static void
-s_register (ignore)
- int ignore ATTRIBUTE_UNUSED;
+s_register (int ignore ATTRIBUTE_UNUSED)
{
char c;
int reg;
symbols which need it. */
void
-sparc_adjust_symtab ()
+sparc_adjust_symtab (void)
{
symbolS *sym;
option to check for it. */
void
-sparc_cons_align (nbytes)
- int nbytes;
+sparc_cons_align (int nbytes)
{
int nalign;
char *p;
if (sparc_no_align_cons)
return;
- nalign = log2 (nbytes);
+ nalign = mylog2 (nbytes);
if (nalign == 0)
return;
/* This is called from HANDLE_ALIGN in tc-sparc.h. */
void
-sparc_handle_align (fragp)
- fragS *fragp;
+sparc_handle_align (fragS *fragp)
{
int count, fix;
char *p;
/* Some special processing for a Sparc ELF file. */
void
-sparc_elf_final_processing ()
+sparc_elf_final_processing (void)
{
/* Set the Sparc ELF flag bits. FIXME: There should probably be some
sort of BFD interface for this. */
}
void
-sparc_cons (exp, size)
- expressionS *exp;
- int size;
+sparc_cons (expressionS *exp, int size)
{
char *save;
we want to handle little endian relocs specially. */
void
-cons_fix_new_sparc (frag, where, nbytes, exp)
- fragS *frag;
- int where;
- unsigned int nbytes;
- expressionS *exp;
+cons_fix_new_sparc (fragS *frag,
+ int where,
+ unsigned int nbytes,
+ expressionS *exp)
{
bfd_reloc_code_real_type r;
}
void
-sparc_cfi_frame_initial_instructions ()
+sparc_cfi_frame_initial_instructions (void)
{
cfi_add_CFA_def_cfa (14, sparc_arch_size == 64 ? 0x7ff : 0);
}
int
-sparc_regname_to_dw2regnum (const char *regname)
+sparc_regname_to_dw2regnum (char *regname)
{
char *p, *q;