/* GAS interface for targets using CGEN: Cpu tools GENerator.
- Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
- 2006, 2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 1996-2020 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
along with GAS; see the file COPYING. If not, write to the Free Software
Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
-#include <setjmp.h>
#include "as.h"
+#include <setjmp.h>
#include "symcat.h"
#include "cgen-desc.h"
#include "subsegs.h"
#include "dwarf2dbg.h"
#include "symbols.h"
-#include "struc-symbol.h"
#ifdef OBJ_COMPLEX_RELC
static expressionS * make_right_shifted_expr
const unsigned long, const unsigned long, const unsigned long, \
const unsigned long);
-static char * weak_operand_overflow_check
+static const char * weak_operand_overflow_check
(const expressionS *, const CGEN_OPERAND *);
static void queue_fixup_recursively
??? Not currently used. */
void
-cgen_asm_record_register (name, number)
- char *name;
- int number;
+cgen_asm_record_register (char *name, int number)
{
/* Use symbol_create here instead of symbol_new so we don't try to
output registers into the object file's symbol table. */
??? May wish to make this static and delete calls in md_assemble. */
void
-gas_cgen_init_parse ()
+gas_cgen_init_parse (void)
{
num_fixups = 0;
}
/* Queue a fixup. */
static void
-queue_fixup (opindex, opinfo, expP)
- int opindex;
- int opinfo;
- expressionS * expP;
+queue_fixup (int opindex, int opinfo, expressionS *expP)
{
/* We need to generate a fixup for this expression. */
if (num_fixups >= GAS_CGEN_MAX_FIXUPS)
static struct saved_fixups stored_fixups[MAX_SAVED_FIXUP_CHAINS];
void
-gas_cgen_initialize_saved_fixups_array ()
+gas_cgen_initialize_saved_fixups_array (void)
{
int i = 0;
}
void
-gas_cgen_save_fixups (i)
- int i;
+gas_cgen_save_fixups (int i)
{
if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS)
{
}
void
-gas_cgen_restore_fixups (i)
- int i;
+gas_cgen_restore_fixups (int i)
{
if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS)
{
}
void
-gas_cgen_swap_fixups (i)
- int i;
+gas_cgen_swap_fixups (int i)
{
if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS)
{
operand type. We pick a BFD reloc type in md_apply_fix. */
fixS *
-gas_cgen_record_fixup (frag, where, insn, length, operand, opinfo, symbol, offset)
- fragS * frag;
- int where;
- const CGEN_INSN * insn;
- int length;
- const CGEN_OPERAND * operand;
- int opinfo;
- symbolS * symbol;
- offsetT offset;
+gas_cgen_record_fixup (fragS *frag, int where, const CGEN_INSN *insn,
+ int length, const CGEN_OPERAND *operand, int opinfo,
+ symbolS *symbol, offsetT offset)
{
fixS *fixP;
operand type. We pick a BFD reloc type in md_apply_fix. */
fixS *
-gas_cgen_record_fixup_exp (frag, where, insn, length, operand, opinfo, exp)
- fragS * frag;
- int where;
- const CGEN_INSN * insn;
- int length;
- const CGEN_OPERAND * operand;
- int opinfo;
- expressionS * exp;
+gas_cgen_record_fixup_exp (fragS *frag, int where, const CGEN_INSN *insn,
+ int length, const CGEN_OPERAND *operand, int opinfo,
+ expressionS *exp)
{
fixS *fixP;
The resulting value is stored in VALUEP. */
const char *
-gas_cgen_parse_operand (cd, want, strP, opindex, opinfo, resultP, valueP)
-
-#ifdef OBJ_COMPLEX_RELC
- CGEN_CPU_DESC cd;
-#else
- CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
-#endif
- enum cgen_parse_operand_type want;
- const char **strP;
- int opindex;
- int opinfo;
- enum cgen_parse_operand_result *resultP;
- bfd_vma *valueP;
+gas_cgen_parse_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
+ enum cgen_parse_operand_type want, const char **strP,
+ int opindex, int opinfo,
+ enum cgen_parse_operand_result *resultP,
+ bfd_vma *valueP)
{
#ifdef __STDC__
/* These are volatile to survive the setjmp. */
if (! errmsg)
{
+ asymbol *bsym;
+
/* Fragment the expression as necessary, and queue a reloc. */
memset (& dummy_fixup, 0, sizeof (fixS));
if (exp.X_op == O_symbol
&& reloc_type == BFD_RELOC_RELC
- && exp.X_add_symbol->sy_value.X_op == O_constant
- && (!exp.X_add_symbol->bsym
- || (exp.X_add_symbol->bsym->section != expr_section
- && exp.X_add_symbol->bsym->section != absolute_section
- && exp.X_add_symbol->bsym->section != undefined_section)))
+ && symbol_constant_p (exp.X_add_symbol)
+ && (!symbol_symbolS (exp.X_add_symbol)
+ || (bsym = symbol_get_bfdsym (exp.X_add_symbol)) == NULL
+ || (bsym->section != expr_section
+ && bsym->section != absolute_section
+ && bsym->section != undefined_section)))
{
/* Local labels will have been (eagerly) turned into constants
by now, due to the inappropriately deep insight of the
if (operand && (operand->hw_type == HW_H_SINT))
signed_p = 1;
- if (stmp->bsym && (stmp->bsym->section == expr_section))
+ if (symbol_symbolS (stmp)
+ && (bsym = symbol_get_bfdsym (stmp)) != NULL
+ && bsym->section == expr_section
+ && ! S_IS_LOCAL (stmp))
{
if (signed_p)
- stmp->bsym->flags |= BSF_SRELC;
+ bsym->flags |= BSF_SRELC;
else
- stmp->bsym->flags |= BSF_RELC;
+ bsym->flags |= BSF_RELC;
}
/* Now package it all up for the fixup emitter. */
??? This could be done differently by adding code to `expression'. */
void
-gas_cgen_md_operand (expressionP)
- expressionS *expressionP ATTRIBUTE_UNUSED;
+gas_cgen_md_operand (expressionS *expressionP ATTRIBUTE_UNUSED)
{
/* Don't longjmp if we're not called from within cgen_parse_operand(). */
if (expr_jmp_buf_p)
The "result" is stored in RESULT if non-NULL. */
void
-gas_cgen_finish_insn (insn, buf, length, relax_p, result)
- const CGEN_INSN *insn;
- CGEN_INSN_BYTES_PTR buf;
- unsigned int length;
- int relax_p;
- finished_insnS *result;
+gas_cgen_finish_insn (const CGEN_INSN *insn, CGEN_INSN_BYTES_PTR buf,
+ unsigned int length, int relax_p, finished_insnS *result)
{
int i;
int relax_operand;
overflow, so signal it by returning an error string. Any other case is
ambiguous, so we assume it's OK and return NULL. */
-static char *
+static const char *
weak_operand_overflow_check (const expressionS * exp,
const CGEN_OPERAND * operand)
{
mask = exp->X_add_number;
if (exp->X_add_symbol
- && exp->X_add_symbol->sy_value.X_op == O_constant)
- mask |= exp->X_add_symbol->sy_value.X_add_number;
+ && symbol_constant_p (exp->X_add_symbol))
+ mask |= *symbol_X_add_number (exp->X_add_symbol);
if (exp->X_op_symbol
- && exp->X_op_symbol->sy_value.X_op == O_constant)
- mask |= exp->X_op_symbol->sy_value.X_add_number;
+ && symbol_constant_p (exp->X_op_symbol))
+ mask |= *symbol_X_add_number (exp->X_op_symbol);
/* Want to know if mask covers more bits than opmask.
this is the same as asking if mask has any bits not in opmask,
{
symbolS * stmp = 0;
expressionS * new_exp;
+ asymbol *bsym;
stmp = expr_build_binary (O_right_shift,
make_expr_symbol (exp),
expr_build_uconstant (amount));
+ bsym = symbol_get_bfdsym (stmp);
if (signed_p)
- stmp->bsym->flags |= BSF_SRELC;
+ bsym->flags |= BSF_SRELC;
else
- stmp->bsym->flags |= BSF_RELC;
+ bsym->flags |= BSF_RELC;
/* Then wrap that in a "symbol expr" for good measure. */
- new_exp = xmalloc (sizeof (expressionS));
+ new_exp = XNEW (expressionS);
memset (new_exp, 0, sizeof (expressionS));
new_exp->X_op = O_symbol;
new_exp->X_op_symbol = 0;
should handle them all. */
void
-gas_cgen_md_apply_fix (fixP, valP, seg)
- fixS * fixP;
- valueT * valP;
- segT seg ATTRIBUTE_UNUSED;
+gas_cgen_md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
{
char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
valueT value = * valP;
const CGEN_OPERAND *operand = cgen_operand_lookup_by_num (cd, opindex);
const char *errmsg;
bfd_reloc_code_real_type reloc_type;
- CGEN_FIELDS *fields = alloca (CGEN_CPU_SIZEOF_FIELDS (cd));
const CGEN_INSN *insn = fixP->fx_cgen.insn;
+#ifdef OBJ_COMPLEX_RELC
int start;
int length;
int signed_p = 0;
values will be signed relocs, but it's possible. */
if (operand && (operand->hw_type == HW_H_SINT))
signed_p = 1;
+#endif
/* If the reloc has been fully resolved finish the operand here. */
/* FIXME: This duplicates the capabilities of code in BFD. */
finish the job. Testing for pcrel is a temporary hack. */
|| fixP->fx_pcrel)
{
+ CGEN_FIELDS *fields = xmalloc (CGEN_CPU_SIZEOF_FIELDS (cd));
+
CGEN_CPU_SET_FIELDS_BITSIZE (cd) (fields, CGEN_INSN_BITSIZE (insn));
CGEN_CPU_SET_VMA_OPERAND (cd) (cd, opindex, fields, (bfd_vma) value);
#endif
if (errmsg)
as_bad_where (fixP->fx_file, fixP->fx_line, "%s", errmsg);
+
+ free (fields);
}
if (fixP->fx_done)
fixP->fx_addnumber = value;
}
+bfd_reloc_code_real_type
+gas_cgen_pcrel_r_type (bfd_reloc_code_real_type r)
+{
+ switch (r)
+ {
+ case BFD_RELOC_8: r = BFD_RELOC_8_PCREL; break;
+ case BFD_RELOC_16: r = BFD_RELOC_16_PCREL; break;
+ case BFD_RELOC_24: r = BFD_RELOC_24_PCREL; break;
+ case BFD_RELOC_32: r = BFD_RELOC_32_PCREL; break;
+ case BFD_RELOC_64: r = BFD_RELOC_64_PCREL; break;
+ default:
+ break;
+ }
+ return r;
+}
+
/* Translate internal representation of relocation info to BFD target format.
FIXME: To what extent can we get all relevant targets to use this? */
arelent *
-gas_cgen_tc_gen_reloc (section, fixP)
- asection * section ATTRIBUTE_UNUSED;
- fixS * fixP;
+gas_cgen_tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)
{
+ bfd_reloc_code_real_type r_type = fixP->fx_r_type;
arelent *reloc;
- reloc = (arelent *) xmalloc (sizeof (arelent));
- reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
+ reloc = XNEW (arelent);
+
+#ifdef GAS_CGEN_PCREL_R_TYPE
+ if (fixP->fx_pcrel)
+ r_type = GAS_CGEN_PCREL_R_TYPE (r_type);
+#endif
+ reloc->howto = bfd_reloc_type_lookup (stdoutput, r_type);
+
if (reloc->howto == (reloc_howto_type *) NULL)
{
as_bad_where (fixP->fx_file, fixP->fx_line,
gas_assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
- reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+ reloc->sym_ptr_ptr = XNEW (asymbol *);
*reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
/* Use fx_offset for these cases. */
Called after gas_cgen_cpu_desc has been created. */
void
-gas_cgen_begin ()
+gas_cgen_begin (void)
{
if (flag_signed_overflow_ok)
cgen_set_signed_overflow_ok (gas_cgen_cpu_desc);