gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gas / cgen.c
index 79a46f668a964262f45ef9efc4ce06b45be115ba..b94802ebc8f8f2427c42e16862e72ef13b4fb32b 100644 (file)
@@ -1,6 +1,5 @@
 /* GAS interface for targets using CGEN: Cpu tools GENerator.
-   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-   2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 1996-2020 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -18,8 +17,8 @@
    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"
@@ -27,7 +26,6 @@
 #include "dwarf2dbg.h"
 
 #include "symbols.h"
-#include "struc-symbol.h"
 
 #ifdef OBJ_COMPLEX_RELC
 static expressionS * make_right_shifted_expr
@@ -38,7 +36,7 @@ static unsigned long gas_cgen_encode_addend
    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
@@ -58,9 +56,7 @@ CGEN_CPU_DESC gas_cgen_cpu_desc;
    ??? 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.  */
@@ -95,7 +91,7 @@ static int num_fixups;
    ??? 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;
 }
@@ -103,10 +99,7 @@ gas_cgen_init_parse ()
 /* 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)
@@ -160,7 +153,7 @@ struct saved_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;
 
@@ -169,8 +162,7 @@ gas_cgen_initialize_saved_fixups_array ()
 }
 
 void
-gas_cgen_save_fixups (i)
-     int i;
+gas_cgen_save_fixups (int i)
 {
   if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS)
     {
@@ -185,8 +177,7 @@ gas_cgen_save_fixups (i)
 }
 
 void
-gas_cgen_restore_fixups (i)
-     int i;
+gas_cgen_restore_fixups (int i)
 {
   if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS)
     {
@@ -201,8 +192,7 @@ gas_cgen_restore_fixups (i)
 }
 
 void
-gas_cgen_swap_fixups (i)
-     int i;
+gas_cgen_swap_fixups (int i)
 {
   if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS)
     {
@@ -248,15 +238,9 @@ gas_cgen_swap_fixups (i)
    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;
 
@@ -289,14 +273,9 @@ gas_cgen_record_fixup (frag, where, insn, length, operand, opinfo, symbol, offse
    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;
 
@@ -345,19 +324,11 @@ static int expr_jmp_buf_p;
    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.  */
@@ -410,7 +381,7 @@ gas_cgen_parse_operand (cd, want, strP, opindex, opinfo, resultP, valueP)
 
 #ifdef TC_CGEN_PARSE_FIX_EXP
   opinfo_1 = TC_CGEN_PARSE_FIX_EXP (opinfo_1, & exp);
-#endif 
+#endif
 
   /* FIXME: Need to check `want'.  */
 
@@ -444,6 +415,8 @@ gas_cgen_parse_operand (cd, want, strP, opindex, opinfo, resultP, valueP)
 
       if (! errmsg)
        {
+         asymbol *bsym;
+
          /* Fragment the expression as necessary, and queue a reloc.  */
          memset (& dummy_fixup, 0, sizeof (fixS));
 
@@ -451,11 +424,12 @@ gas_cgen_parse_operand (cd, want, strP, opindex, opinfo, resultP, valueP)
 
          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
@@ -466,15 +440,15 @@ gas_cgen_parse_operand (cd, want, strP, opindex, opinfo, resultP, valueP)
              stmp = symbol_create (FAKE_LABEL_NAME, expr_section, 0,
                                    & zero_address_frag);
              symbol_set_value_expression (stmp, & exp);
-           } 
-         else 
+           }
+         else
            stmp = make_expr_symbol (& exp);
 
          /* If this is a pc-relative RELC operand, we
-            need to subtract "." from the expression.  */        
+            need to subtract "." from the expression.  */
          if (reloc_type == BFD_RELOC_RELC
              && CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_PCREL_ADDR))
-           stmp = expr_build_binary (O_subtract, stmp, expr_build_dot ()); 
+           stmp = expr_build_binary (O_subtract, stmp, expr_build_dot ());
 
          /* FIXME: this is not a perfect heuristic for figuring out
             whether an operand is signed: it only works when the operand
@@ -482,24 +456,27 @@ gas_cgen_parse_operand (cd, want, strP, opindex, opinfo, resultP, valueP)
             values will be signed relocs, but it's possible. */
          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.  */
          exp.X_op = O_symbol;
          exp.X_op_symbol = 0;
          exp.X_add_symbol = stmp;
          exp.X_add_number = 0;
-             
+
          /* Re-init rightshift quantity, just in case.  */
          rightshift = operand->length;
-         queue_fixup_recursively (opindex, opinfo_1, & exp,  
+         queue_fixup_recursively (opindex, opinfo_1, & exp,
                                   (reloc_type == BFD_RELOC_RELC) ?
                                   & (operand->index_fields) : 0,
                                   signed_p, -1);
@@ -512,7 +489,7 @@ gas_cgen_parse_operand (cd, want, strP, opindex, opinfo, resultP, valueP)
       queue_fixup (opindex, opinfo_1, &exp);
       *valueP = 0;
       *resultP = CGEN_PARSE_OPERAND_RESULT_QUEUED;
-#endif      
+#endif
       break;
     }
 
@@ -525,8 +502,7 @@ gas_cgen_parse_operand (cd, want, strP, opindex, opinfo, resultP, valueP)
    ??? 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)
@@ -541,12 +517,8 @@ gas_cgen_md_operand (expressionP)
    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;
@@ -710,9 +682,9 @@ queue_fixup_recursively (const int                      opindex,
   if (field && field->count)
     {
       int i;
-  
+
       for (i = 0; i < field->count; ++ i)
-       queue_fixup_recursively (opindex, opinfo, expP, 
+       queue_fixup_recursively (opindex, opinfo, expP,
                                 & (field->val.multi[i]), signed_p, i);
     }
   else
@@ -731,20 +703,20 @@ queue_fixup_recursively (const int                      opindex,
          /* Shift reloc value by number of bits remaining after this
             field.  */
          if (rightshift)
-           new_exp = make_right_shifted_expr (expP, rightshift, signed_p);       
+           new_exp = make_right_shifted_expr (expP, rightshift, signed_p);
        }
-      
+
       /* Truncate reloc values to length, *after* leftmost one.  */
       fixups[num_fixups].msb_field_p = (part_of_multi <= 0);
       fixups[num_fixups].field = (CGEN_MAYBE_MULTI_IFLD *) field;
-      
+
       queue_fixup (opindex, opinfo, new_exp);
     }
 }
 
 /* Encode the self-describing RELC reloc format's addend.  */
 
-static unsigned long 
+static unsigned long
 gas_cgen_encode_addend (const unsigned long start,    /* in bits */
                        const unsigned long len,      /* in bits */
                        const unsigned long oplen,    /* in bits */
@@ -774,13 +746,13 @@ gas_cgen_encode_addend (const unsigned long start,    /* in bits */
    parse. when these %operators are translated to expressions by the macro
    expander, the ambiguity returns. we attempt to disambiguate by field
    size.
-   
+
    Method: check to see if the expression's top node is an O_and operator,
    and the mask is larger than the operand length. This would be an
    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)
 {
@@ -794,23 +766,23 @@ weak_operand_overflow_check (const expressionS *  exp,
   if (exp->X_op != O_bit_and)
     {
       /* Check for implicit overflow flag.  */
-      if (CGEN_OPERAND_ATTR_VALUE 
+      if (CGEN_OPERAND_ATTR_VALUE
          (operand, CGEN_OPERAND_RELOC_IMPLIES_OVERFLOW))
        return _("a reloc on this operand implies an overflow");
       return NULL;
     }
-  
+
   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;
+  if (exp->X_add_symbol
+      && 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;
+  if (exp->X_op_symbol
+      && 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. 
+  /* Want to know if mask covers more bits than opmask.
      this is the same as asking if mask has any bits not in opmask,
      or whether (mask & ~opmask) is nonzero.  */
   if (mask && (mask & ~opmask))
@@ -822,10 +794,9 @@ weak_operand_overflow_check (const expressionS *  exp,
       return _("operand mask overflow");
     }
 
-  return NULL;  
+  return NULL;
 }
 
-
 static expressionS *
 make_right_shifted_expr (expressionS * exp,
                         const int     amount,
@@ -833,27 +804,31 @@ make_right_shifted_expr (expressionS * exp,
 {
   symbolS * stmp = 0;
   expressionS * new_exp;
+  asymbol *bsym;
 
-  stmp = expr_build_binary (O_right_shift, 
+  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;
   new_exp->X_add_symbol = stmp;
   new_exp->X_add_number = 0;
-  
+
   return new_exp;
 }
+
 #endif
+
 /* Apply a fixup to the object code.  This is called for all the
    fixups we generated by the call to fix_new_exp, above.  In the call
    above we used a reloc code which was the largest legal reloc code
@@ -867,10 +842,7 @@ make_right_shifted_expr (expressionS * exp,
    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;
@@ -890,14 +862,14 @@ gas_cgen_md_apply_fix (fixP, valP, seg)
       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;
 
       if (fixP->fx_cgen.field)
-       {             
+       {
          /* Use the twisty little pointer path
             back to the ifield if it exists.  */
          start = fixP->fx_cgen.field->val.leaf->start;
@@ -916,6 +888,7 @@ gas_cgen_md_apply_fix (fixP, valP, seg)
          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.  */
@@ -924,6 +897,8 @@ gas_cgen_md_apply_fix (fixP, valP, seg)
             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);
 
@@ -947,6 +922,8 @@ gas_cgen_md_apply_fix (fixP, valP, seg)
 #endif
          if (errmsg)
            as_bad_where (fixP->fx_file, fixP->fx_line, "%s", errmsg);
+
+         free (fields);
        }
 
       if (fixP->fx_done)
@@ -964,9 +941,9 @@ gas_cgen_md_apply_fix (fixP, valP, seg)
          /* Change addend to "self-describing" form,
             for BFD to handle in the linker.  */
          value = gas_cgen_encode_addend (start, operand->length,
-                                         length, fixP->fx_size, 
-                                         cd->insn_chunk_bitsize / 8, 
-                                         signed_p, 
+                                         length, fixP->fx_size,
+                                         cd->insn_chunk_bitsize / 8,
+                                         signed_p,
                                          ! (fixP->fx_cgen.msb_field_p));
        }
 #endif
@@ -1015,19 +992,40 @@ gas_cgen_md_apply_fix (fixP, valP, seg)
   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,
@@ -1035,9 +1033,9 @@ gas_cgen_tc_gen_reloc (section, fixP)
       return NULL;
     }
 
-  assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
+  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.  */
@@ -1055,11 +1053,10 @@ gas_cgen_tc_gen_reloc (section, fixP)
    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);
   else
     cgen_clear_signed_overflow_ok (gas_cgen_cpu_desc);
 }
-
This page took 0.031264 seconds and 4 git commands to generate.