static void arc_extra_reloc (int);
const pseudo_typeS md_pseudo_table[] =
- {
- /* Make sure that .word is 32 bits. */
- { "word", cons, 4 },
+{
+ /* Make sure that .word is 32 bits. */
+ { "word", cons, 4 },
- { "align", s_align_bytes, 0 }, /* Defaulting is invalid (0). */
- { "lcomm", arc_lcomm, 0 },
- { "lcommon", arc_lcomm, 0 },
- { "cpu", arc_option, 0 },
+ { "align", s_align_bytes, 0 }, /* Defaulting is invalid (0). */
+ { "lcomm", arc_lcomm, 0 },
+ { "lcommon", arc_lcomm, 0 },
+ { "cpu", arc_option, 0 },
- { "tls_gd_ld", arc_extra_reloc, BFD_RELOC_ARC_TLS_GD_LD },
- { "tls_gd_call", arc_extra_reloc, BFD_RELOC_ARC_TLS_GD_CALL },
+ { "tls_gd_ld", arc_extra_reloc, BFD_RELOC_ARC_TLS_GD_LD },
+ { "tls_gd_call", arc_extra_reloc, BFD_RELOC_ARC_TLS_GD_CALL },
- { NULL, NULL, 0 }
- };
+ { NULL, NULL, 0 }
+};
const char *md_shortopts = "";
enum options
- {
- OPTION_EB = OPTION_MD_BASE,
- OPTION_EL,
-
- OPTION_ARC600,
- OPTION_ARC601,
- OPTION_ARC700,
- OPTION_ARCEM,
- OPTION_ARCHS,
-
- OPTION_MCPU,
- OPTION_CD,
-
- /* The following options are deprecated and provided here only for
- compatibility reasons. */
- OPTION_USER_MODE,
- OPTION_LD_EXT_MASK,
- OPTION_SWAP,
- OPTION_NORM,
- OPTION_BARREL_SHIFT,
- OPTION_MIN_MAX,
- OPTION_NO_MPY,
- OPTION_EA,
- OPTION_MUL64,
- OPTION_SIMD,
- OPTION_SPFP,
- OPTION_DPFP,
- OPTION_XMAC_D16,
- OPTION_XMAC_24,
- OPTION_DSP_PACKA,
- OPTION_CRC,
- OPTION_DVBF,
- OPTION_TELEPHONY,
- OPTION_XYMEMORY,
- OPTION_LOCK,
- OPTION_SWAPE,
- OPTION_RTSC,
- OPTION_FPUDA
- };
+{
+ OPTION_EB = OPTION_MD_BASE,
+ OPTION_EL,
+
+ OPTION_ARC600,
+ OPTION_ARC601,
+ OPTION_ARC700,
+ OPTION_ARCEM,
+ OPTION_ARCHS,
+
+ OPTION_MCPU,
+ OPTION_CD,
+
+ /* The following options are deprecated and provided here only for
+ compatibility reasons. */
+ OPTION_USER_MODE,
+ OPTION_LD_EXT_MASK,
+ OPTION_SWAP,
+ OPTION_NORM,
+ OPTION_BARREL_SHIFT,
+ OPTION_MIN_MAX,
+ OPTION_NO_MPY,
+ OPTION_EA,
+ OPTION_MUL64,
+ OPTION_SIMD,
+ OPTION_SPFP,
+ OPTION_DPFP,
+ OPTION_XMAC_D16,
+ OPTION_XMAC_24,
+ OPTION_DSP_PACKA,
+ OPTION_CRC,
+ OPTION_DVBF,
+ OPTION_TELEPHONY,
+ OPTION_XYMEMORY,
+ OPTION_LOCK,
+ OPTION_SWAPE,
+ OPTION_RTSC,
+ OPTION_FPUDA
+};
struct option md_longopts[] =
- {
- { "EB", no_argument, NULL, OPTION_EB },
- { "EL", no_argument, NULL, OPTION_EL },
- { "mcpu", required_argument, NULL, OPTION_MCPU },
- { "mA6", no_argument, NULL, OPTION_ARC600 },
- { "mARC600", no_argument, NULL, OPTION_ARC600 },
- { "mARC601", no_argument, NULL, OPTION_ARC601 },
- { "mARC700", no_argument, NULL, OPTION_ARC700 },
- { "mA7", no_argument, NULL, OPTION_ARC700 },
- { "mEM", no_argument, NULL, OPTION_ARCEM },
- { "mHS", no_argument, NULL, OPTION_ARCHS },
- { "mcode-density", no_argument, NULL, OPTION_CD },
-
- /* The following options are deprecated and provided here only for
- compatibility reasons. */
- { "mav2em", no_argument, NULL, OPTION_ARCEM },
- { "mav2hs", no_argument, NULL, OPTION_ARCHS },
- { "muser-mode-only", no_argument, NULL, OPTION_USER_MODE },
- { "mld-extension-reg-mask", required_argument, NULL, OPTION_LD_EXT_MASK },
- { "mswap", no_argument, NULL, OPTION_SWAP },
- { "mnorm", no_argument, NULL, OPTION_NORM },
- { "mbarrel-shifter", no_argument, NULL, OPTION_BARREL_SHIFT },
- { "mbarrel_shifter", no_argument, NULL, OPTION_BARREL_SHIFT },
- { "mmin-max", no_argument, NULL, OPTION_MIN_MAX },
- { "mmin_max", no_argument, NULL, OPTION_MIN_MAX },
- { "mno-mpy", no_argument, NULL, OPTION_NO_MPY },
- { "mea", no_argument, NULL, OPTION_EA },
- { "mEA", no_argument, NULL, OPTION_EA },
- { "mmul64", no_argument, NULL, OPTION_MUL64 },
- { "msimd", no_argument, NULL, OPTION_SIMD},
- { "mspfp", no_argument, NULL, OPTION_SPFP},
- { "mspfp-compact", no_argument, NULL, OPTION_SPFP},
- { "mspfp_compact", no_argument, NULL, OPTION_SPFP},
- { "mspfp-fast", no_argument, NULL, OPTION_SPFP},
- { "mspfp_fast", no_argument, NULL, OPTION_SPFP},
- { "mdpfp", no_argument, NULL, OPTION_DPFP},
- { "mdpfp-compact", no_argument, NULL, OPTION_DPFP},
- { "mdpfp_compact", no_argument, NULL, OPTION_DPFP},
- { "mdpfp-fast", no_argument, NULL, OPTION_DPFP},
- { "mdpfp_fast", no_argument, NULL, OPTION_DPFP},
- { "mmac-d16", no_argument, NULL, OPTION_XMAC_D16},
- { "mmac_d16", no_argument, NULL, OPTION_XMAC_D16},
- { "mmac-24", no_argument, NULL, OPTION_XMAC_24},
- { "mmac_24", no_argument, NULL, OPTION_XMAC_24},
- { "mdsp-packa", no_argument, NULL, OPTION_DSP_PACKA},
- { "mdsp_packa", no_argument, NULL, OPTION_DSP_PACKA},
- { "mcrc", no_argument, NULL, OPTION_CRC},
- { "mdvbf", no_argument, NULL, OPTION_DVBF},
- { "mtelephony", no_argument, NULL, OPTION_TELEPHONY},
- { "mxy", no_argument, NULL, OPTION_XYMEMORY},
- { "mlock", no_argument, NULL, OPTION_LOCK},
- { "mswape", no_argument, NULL, OPTION_SWAPE},
- { "mrtsc", no_argument, NULL, OPTION_RTSC},
- { "mfpuda", no_argument, NULL, OPTION_FPUDA},
-
- { NULL, no_argument, NULL, 0 }
- };
+{
+ { "EB", no_argument, NULL, OPTION_EB },
+ { "EL", no_argument, NULL, OPTION_EL },
+ { "mcpu", required_argument, NULL, OPTION_MCPU },
+ { "mA6", no_argument, NULL, OPTION_ARC600 },
+ { "mARC600", no_argument, NULL, OPTION_ARC600 },
+ { "mARC601", no_argument, NULL, OPTION_ARC601 },
+ { "mARC700", no_argument, NULL, OPTION_ARC700 },
+ { "mA7", no_argument, NULL, OPTION_ARC700 },
+ { "mEM", no_argument, NULL, OPTION_ARCEM },
+ { "mHS", no_argument, NULL, OPTION_ARCHS },
+ { "mcode-density", no_argument, NULL, OPTION_CD },
+
+ /* The following options are deprecated and provided here only for
+ compatibility reasons. */
+ { "mav2em", no_argument, NULL, OPTION_ARCEM },
+ { "mav2hs", no_argument, NULL, OPTION_ARCHS },
+ { "muser-mode-only", no_argument, NULL, OPTION_USER_MODE },
+ { "mld-extension-reg-mask", required_argument, NULL, OPTION_LD_EXT_MASK },
+ { "mswap", no_argument, NULL, OPTION_SWAP },
+ { "mnorm", no_argument, NULL, OPTION_NORM },
+ { "mbarrel-shifter", no_argument, NULL, OPTION_BARREL_SHIFT },
+ { "mbarrel_shifter", no_argument, NULL, OPTION_BARREL_SHIFT },
+ { "mmin-max", no_argument, NULL, OPTION_MIN_MAX },
+ { "mmin_max", no_argument, NULL, OPTION_MIN_MAX },
+ { "mno-mpy", no_argument, NULL, OPTION_NO_MPY },
+ { "mea", no_argument, NULL, OPTION_EA },
+ { "mEA", no_argument, NULL, OPTION_EA },
+ { "mmul64", no_argument, NULL, OPTION_MUL64 },
+ { "msimd", no_argument, NULL, OPTION_SIMD},
+ { "mspfp", no_argument, NULL, OPTION_SPFP},
+ { "mspfp-compact", no_argument, NULL, OPTION_SPFP},
+ { "mspfp_compact", no_argument, NULL, OPTION_SPFP},
+ { "mspfp-fast", no_argument, NULL, OPTION_SPFP},
+ { "mspfp_fast", no_argument, NULL, OPTION_SPFP},
+ { "mdpfp", no_argument, NULL, OPTION_DPFP},
+ { "mdpfp-compact", no_argument, NULL, OPTION_DPFP},
+ { "mdpfp_compact", no_argument, NULL, OPTION_DPFP},
+ { "mdpfp-fast", no_argument, NULL, OPTION_DPFP},
+ { "mdpfp_fast", no_argument, NULL, OPTION_DPFP},
+ { "mmac-d16", no_argument, NULL, OPTION_XMAC_D16},
+ { "mmac_d16", no_argument, NULL, OPTION_XMAC_D16},
+ { "mmac-24", no_argument, NULL, OPTION_XMAC_24},
+ { "mmac_24", no_argument, NULL, OPTION_XMAC_24},
+ { "mdsp-packa", no_argument, NULL, OPTION_DSP_PACKA},
+ { "mdsp_packa", no_argument, NULL, OPTION_DSP_PACKA},
+ { "mcrc", no_argument, NULL, OPTION_CRC},
+ { "mdvbf", no_argument, NULL, OPTION_DVBF},
+ { "mtelephony", no_argument, NULL, OPTION_TELEPHONY},
+ { "mxy", no_argument, NULL, OPTION_XYMEMORY},
+ { "mlock", no_argument, NULL, OPTION_LOCK},
+ { "mswape", no_argument, NULL, OPTION_SWAPE},
+ { "mrtsc", no_argument, NULL, OPTION_RTSC},
+ { "mfpuda", no_argument, NULL, OPTION_FPUDA},
+
+ { NULL, no_argument, NULL, 0 }
+};
size_t md_longopts_size = sizeof (md_longopts);
unsigned int complex_expr : 1;
}
arc_reloc_op[] =
- {
- DEF (gotoff, BFD_RELOC_ARC_GOTOFF, 1),
- DEF (gotpc, BFD_RELOC_ARC_GOTPC32, 0),
- DEF (plt, BFD_RELOC_ARC_PLT32, 0),
- DEF (sda, DUMMY_RELOC_ARC_ENTRY, 1),
- DEF (pcl, BFD_RELOC_ARC_PC32, 1),
- DEF (tlsgd, BFD_RELOC_ARC_TLS_GD_GOT, 0),
- DEF (tlsie, BFD_RELOC_ARC_TLS_IE_GOT, 0),
- DEF (tpoff9, BFD_RELOC_ARC_TLS_LE_S9, 0),
- DEF (tpoff, BFD_RELOC_ARC_TLS_LE_32, 0),
- DEF (dtpoff9, BFD_RELOC_ARC_TLS_DTPOFF_S9, 0),
- DEF (dtpoff, BFD_RELOC_ARC_TLS_DTPOFF, 0),
- };
+{
+ DEF (gotoff, BFD_RELOC_ARC_GOTOFF, 1),
+ DEF (gotpc, BFD_RELOC_ARC_GOTPC32, 0),
+ DEF (plt, BFD_RELOC_ARC_PLT32, 0),
+ DEF (sda, DUMMY_RELOC_ARC_ENTRY, 1),
+ DEF (pcl, BFD_RELOC_ARC_PC32, 1),
+ DEF (tlsgd, BFD_RELOC_ARC_TLS_GD_GOT, 0),
+ DEF (tlsie, BFD_RELOC_ARC_TLS_IE_GOT, 0),
+ DEF (tpoff9, BFD_RELOC_ARC_TLS_LE_S9, 0),
+ DEF (tpoff, BFD_RELOC_ARC_TLS_LE_32, 0),
+ DEF (dtpoff9, BFD_RELOC_ARC_TLS_DTPOFF_S9, 0),
+ DEF (dtpoff, BFD_RELOC_ARC_TLS_DTPOFF, 0),
+};
static const int arc_num_reloc_op
= sizeof (arc_reloc_op) / sizeof (*arc_reloc_op);
this function is used for regular 4 byte instructions as well. */
static void
-md_number_to_chars_midend (char *buf,
- valueT val,
- int n)
+md_number_to_chars_midend (char *buf, valueT val, int n)
{
if (n == 4)
{
bfd_boolean saw_arg = FALSE;
int brk_lvl = 0;
int num_args = 0;
- const char *p;
int i;
size_t len;
const struct arc_reloc_op_tag *r;
expressionS tmpE;
+ char *reloc_name, c;
memset (tok, 0, sizeof (*tok) * ntok);
if (*input_line_pointer != '@')
goto normalsymbol; /* This is not a relocation. */
+ relocationsym:
+
/* A relocation opernad has the following form
@identifier@relocation_type. The identifier is already
in tok! */
}
/* Parse @relocation_type. */
- memset (&tmpE, 0, sizeof (tmpE));
- tmpE.X_op = O_symbol;
- expression (&tmpE);
-
- if (tmpE.X_op != O_symbol)
+ input_line_pointer++;
+ c = get_symbol_name (&reloc_name);
+ len = input_line_pointer - reloc_name;
+ if (len == 0)
{
as_bad (_("No relocation operand"));
goto err;
}
- p = S_GET_NAME (tmpE.X_add_symbol);
- len = strlen (p);
/* Go through known relocation and try to find a match. */
r = &arc_reloc_op[0];
for (i = arc_num_reloc_op - 1; i >= 0; i--, r++)
- if (len == r->length && memcmp (p, r->name, len) == 0)
+ if (len == r->length
+ && memcmp (reloc_name, r->name, len) == 0)
break;
-
if (i < 0)
{
- as_bad (_("Unknown relocation operand: @%s"), p);
- goto err;
- }
- tok->X_md = r->op;
- tok->X_add_number = tmpE.X_add_number;
- if (tmpE.X_add_number && !r->complex_expr)
- {
- as_bad (_("Complex relocation operand."));
+ as_bad (_("Unknown relocation operand: @%s"), reloc_name);
goto err;
}
+ *input_line_pointer = c;
+ SKIP_WHITESPACE_AFTER_NAME ();
/* Extra check for TLS: base. */
if (*input_line_pointer == '@')
{
if (tok->X_op_symbol != NULL
|| tok->X_op != O_symbol)
{
- as_bad (_("Unable to parse this reloc"));
+ as_bad (_("Unable to parse TLS base: %s"),
+ input_line_pointer);
goto err;
}
input_line_pointer++;
char *sym_name;
- char c = get_symbol_name (&sym_name);
+ c = get_symbol_name (&sym_name);
base = symbol_find_or_make (sym_name);
tok->X_op = O_subtract;
tok->X_op_symbol = base;
restore_line_pointer (c);
+ tmpE.X_add_number = 0;
+ }
+ else if ((*input_line_pointer != '+')
+ && (*input_line_pointer != '-'))
+ {
+ tmpE.X_add_number = 0;
}
+ else
+ {
+ /* Parse the constant of a complex relocation expression
+ like @identifier@reloc +/- const. */
+ if (! r->complex_expr)
+ {
+ as_bad (_("@%s is not a complex relocation."), r->name);
+ goto err;
+ }
+ expression (&tmpE);
+ if (tmpE.X_op != O_constant)
+ {
+ as_bad (_("Bad expression: @%s + %s."),
+ r->name, input_line_pointer);
+ goto err;
+ }
+ }
+
+ tok->X_md = r->op;
+ tok->X_add_number = tmpE.X_add_number;
debug_exp (tok);
goto err;
tok->X_op = O_absent;
+ tok->X_md = O_absent;
expression (tok);
+ /* Legacy: There are cases when we have
+ identifier@relocation_type, if it is the case parse the
+ relocation type as well. */
+ if (*input_line_pointer == '@')
+ goto relocationsym;
+
normalsymbol:
debug_exp (tok);
fixP->fx_r_type = BFD_RELOC_ARC_PC32;
/* Fall through. */
case BFD_RELOC_ARC_PC32:
+ /* fixP->fx_offset += fixP->fx_where - fixP->fx_dot_value; */
break;
default:
if ((int) fixP->fx_r_type < 0)
bfd_get_reloc_code_name (fixP->fx_r_type), value,
fixP->fx_offset);
+
+ /* Now check for TLS relocations. */
+ reloc = fixP->fx_r_type;
+ switch (reloc)
+ {
+ case BFD_RELOC_ARC_TLS_DTPOFF:
+ case BFD_RELOC_ARC_TLS_LE_32:
+ fixP->fx_offset = 0;
+ /* Fall through. */
+ case BFD_RELOC_ARC_TLS_GD_GOT:
+ case BFD_RELOC_ARC_TLS_IE_GOT:
+ S_SET_THREAD_LOCAL (fixP->fx_addsy);
+ break;
+
+ case BFD_RELOC_ARC_TLS_GD_LD:
+ gas_assert (!fixP->fx_offset);
+ if (fixP->fx_subsy)
+ fixP->fx_offset
+ = (S_GET_VALUE (fixP->fx_subsy)
+ - fixP->fx_frag->fr_address- fixP->fx_where);
+ fixP->fx_subsy = NULL;
+ /* Fall through. */
+ case BFD_RELOC_ARC_TLS_GD_CALL:
+ /* These two relocs are there just to allow ld to change the tls
+ model for this symbol, by patching the code. The offset -
+ and scale, if any - will be installed by the linker. */
+ S_SET_THREAD_LOCAL (fixP->fx_addsy);
+ break;
+
+ case BFD_RELOC_ARC_TLS_LE_S9:
+ case BFD_RELOC_ARC_TLS_DTPOFF_S9:
+ as_bad (_("TLS_*_S9 relocs are not supported yet"));
+ break;
+
+ default:
+ break;
+ }
+
if (!fixP->fx_done)
- return;
+ {
+ return;
+ }
/* Addjust the value if we have a constant. */
value += fx_offset;
case BFD_RELOC_24:
case BFD_RELOC_32:
case BFD_RELOC_64:
+ case BFD_RELOC_ARC_32_PCREL:
md_number_to_chars (fixpos, value, fixP->fx_size);
return;
gas_assert (operand);
break;
- case BFD_RELOC_ARC_TLS_DTPOFF:
- case BFD_RELOC_ARC_TLS_LE_32:
- if (fixP->fx_done)
- {
- gas_assert (!fixP->fx_addsy);
- gas_assert (!fixP->fx_subsy);
- md_number_to_chars_midend (fixpos, value, fixP->fx_size);
- return;
- }
- else
- {
- value = fixP->fx_offset;
- fixP->fx_offset = 0;
- }
- /* Fall through. */
- case BFD_RELOC_ARC_TLS_GD_GOT:
- case BFD_RELOC_ARC_TLS_IE_GOT:
- S_SET_THREAD_LOCAL (fixP->fx_addsy);
- md_number_to_chars_midend (fixpos, value, fixP->fx_size);
- return;
-
- case BFD_RELOC_ARC_TLS_GD_LD:
- gas_assert (!fixP->fx_offset);
- if (fixP->fx_subsy)
- fixP->fx_offset
- = (S_GET_VALUE (fixP->fx_subsy)
- - fixP->fx_frag->fr_address- fixP->fx_where);
- fixP->fx_subsy = NULL;
- /* Fall through. */
- case BFD_RELOC_ARC_TLS_GD_CALL:
- /* These two relocs are there just to allow ld to change the tls
- model for this symbol, by patching the code. */
- /* Fall through. */
- /* The offset - and scale, if any - will be installed by the
- linker. */
- gas_assert (!fixP->fx_done);
- S_SET_THREAD_LOCAL (fixP->fx_addsy);
- return;
-
- case BFD_RELOC_ARC_TLS_LE_S9:
- case BFD_RELOC_ARC_TLS_DTPOFF_S9:
- as_bad (_("TLS_*_S9 relocs are not supported yet"));
- break;
-
default:
{
if ((int) fixP->fx_r_type >= 0)
&& exp->X_op == O_subtract
&& exp->X_op_symbol != NULL
&& exp->X_op_symbol->bsym->section == now_seg)
- *r_type_p = BFD_RELOC_ARC_PC32;
+ *r_type_p = BFD_RELOC_ARC_32_PCREL;
}