* expr.c (operand): Check more correctly that there is no advance
[deliverable/binutils-gdb.git] / gas / cgen.c
index d65526d993293b5680765c3ef168ac10c537fe69..45d0fe0a5f7568c7d2e66831dca717dba63a6ea5 100644 (file)
@@ -1,5 +1,5 @@
 /* GAS interface for targets using CGEN: Cpu tools GENerator.
-   Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
 
 This file is part of GAS, the GNU Assembler.
 
@@ -20,9 +20,11 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
 #include <setjmp.h>
 #include "ansidecl.h"
 #include "bfd.h"
+#include "symcat.h"
 #include "cgen-opc.h"
 #include "as.h"
 #include "subsegs.h"
+#include "cgen.h"
 
 /* Callback to insert a register into the symbol table.
    A target may choose to let GAS parse the registers.
@@ -31,7 +33,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
 void
 cgen_asm_record_register (name, number)
      char * name;
-     int    number;
+     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.  */
@@ -52,15 +54,13 @@ cgen_asm_record_register (name, number)
 
 struct fixup
 {
-  int         opindex;
-  int         opinfo;
+  int opindex;
+  int opinfo;
   expressionS exp;
 };
 
-#define MAX_FIXUPS 5
-
-static struct fixup fixups [MAX_FIXUPS];
-static int          num_fixups;
+static struct fixup fixups [CGEN_MAX_FIXUPS];
+static int num_fixups;
 
 /* Prepare to parse an instruction.
    ??? May wish to make this static and delete calls in md_assemble.  */
@@ -73,20 +73,76 @@ cgen_asm_init_parse ()
 
 /* Queue a fixup.  */
 
-void
+static void
 cgen_queue_fixup (opindex, opinfo, expP)
      int           opindex;
      expressionS * expP;
 {
   /* We need to generate a fixup for this expression.  */
-  if (num_fixups >= MAX_FIXUPS)
-    as_fatal ("too many fixups");
+  if (num_fixups >= CGEN_MAX_FIXUPS)
+    as_fatal (_("too many fixups"));
   fixups[num_fixups].exp     = * expP;
   fixups[num_fixups].opindex = opindex;
   fixups[num_fixups].opinfo  = opinfo;
   ++ num_fixups;
 }
 
+/* The following three functions allow a backup of the fixup chain to be made,
+   and to have this backup be swapped with the current chain.  This allows
+   certain ports, eg the m32r, to swap two instructions and swap their fixups
+   at the same time.  */
+static struct fixup saved_fixups [CGEN_MAX_FIXUPS];
+static int saved_num_fixups;
+
+void
+cgen_save_fixups ()
+{
+  saved_num_fixups = num_fixups;
+  
+  memcpy (saved_fixups, fixups, sizeof (fixups[0]) * num_fixups);
+
+  num_fixups = 0;
+}
+
+void
+cgen_restore_fixups ()
+{
+  num_fixups = saved_num_fixups;
+  
+  memcpy (fixups, saved_fixups, sizeof (fixups[0]) * num_fixups);
+
+  saved_num_fixups = 0;
+}
+
+void
+cgen_swap_fixups ()
+{
+  int tmp;
+  struct fixup tmp_fixup;
+
+  if (num_fixups == 0)
+    {
+      cgen_restore_fixups ();
+    }
+  else if (saved_num_fixups == 0)
+    {
+      cgen_save_fixups ();
+    }
+  else
+    {
+      tmp = saved_num_fixups;
+      saved_num_fixups = num_fixups;
+      num_fixups = tmp;
+      
+      for (tmp = CGEN_MAX_FIXUPS; tmp--;)
+       {
+         tmp_fixup          = saved_fixups [tmp];
+         saved_fixups [tmp] = fixups [tmp];
+         fixups [tmp]       = tmp_fixup;
+       }
+    }
+}
+
 /* Default routine to record a fixup.
    This is a cover function to fix_new.
    It exists because we record INSN with the fixup.
@@ -178,23 +234,23 @@ static jmp_buf expr_jmp_buf;
 
 const char *
 cgen_parse_operand (want, strP, opindex, opinfo, resultP, valueP)
-     enum cgen_parse_operand_type     want;
-     const char **                    strP;
-     int                              opindex;
-     int                              opinfo;
+     enum cgen_parse_operand_type want;
+     const char ** strP;
+     int opindex;
+     int opinfo;
      enum cgen_parse_operand_result * resultP;
-     bfd_vma *                        valueP;
+     bfd_vma * valueP;
 {
 #ifdef __STDC__
-  /* These is volatile to survive the setjmp.  */
-  char * volatile                           hold;
+  /* These are volatile to survive the setjmp.  */
+  char * volatile hold;
   enum cgen_parse_operand_result * volatile resultP_1;
 #else
-  static char *                             hold;
-  static enum cgen_parse_operand_result *   resultP_1;
+  static char * hold;
+  static enum cgen_parse_operand_result * resultP_1;
 #endif
-  const char *                              errmsg = NULL;
-  expressionS                               exp;
+  const char * errmsg = NULL;
+  expressionS exp;
 
   if (want == CGEN_PARSE_OPERAND_INIT)
     {
@@ -225,11 +281,11 @@ cgen_parse_operand (want, strP, opindex, opinfo, resultP, valueP)
   switch (exp.X_op)
     {
     case O_illegal :
-      errmsg = "illegal operand";
+      errmsg = _("illegal operand");
       * resultP = CGEN_PARSE_OPERAND_RESULT_ERROR;
       break;
     case O_absent :
-      errmsg = "missing operand";
+      errmsg = _("missing operand");
       * resultP = CGEN_PARSE_OPERAND_RESULT_ERROR;
       break;
     case O_constant :
@@ -264,23 +320,28 @@ cgen_md_operand (expressionP)
 
 /* Finish assembling instruction INSN.
    BUF contains what we've built up so far.
-   LENGTH is the size of the insn in bits.  */
+   LENGTH is the size of the insn in bits.
+   RELAX_P is non-zero if relaxable insns should be emitted as such.
+   Otherwise they're emitted in non-relaxable forms.
+   The "result" is stored in RESULT if non-NULL.  */
 
 void
-cgen_asm_finish_insn (insn, buf, length)
+cgen_asm_finish_insn (insn, buf, length, relax_p, result)
      const CGEN_INSN * insn;
-     cgen_insn_t *     buf;
-     unsigned int      length;
+     cgen_insn_t * buf;
+     unsigned int length;
+     int relax_p;
+     finished_insnS * result;
 {
-  int          i;
-  int          relax_operand;
-  char *       f;
+  int i;
+  int relax_operand;
+  char * f;
   unsigned int byte_len = length / 8;
 
   /* ??? Target foo issues various warnings here, so one might want to provide
      a hook here.  However, our caller is defined in tc-foo.c so there
      shouldn't be a need for a hook.  */
-
+  
   /* Write out the instruction.
      It is important to fetch enough space in one call to `frag_more'.
      We use (f - frag_now->fr_literal) to compute where we are and we
@@ -295,7 +356,7 @@ cgen_asm_finish_insn (insn, buf, length)
   /* Is there a relaxable insn with the relaxable operand needing a fixup?  */
 
   relax_operand = -1;
-  if (CGEN_INSN_ATTR (insn, CGEN_INSN_RELAXABLE) != 0)
+  if (relax_p && CGEN_INSN_ATTR (insn, CGEN_INSN_RELAXABLE) != 0)
     {
       /* Scan the fixups for the operand affected by relaxing
         (i.e. the branch address).  */
@@ -313,7 +374,7 @@ cgen_asm_finish_insn (insn, buf, length)
 
   if (relax_operand != -1)
     {
-      int     max_len;
+      int max_len;
       fragS * old_frag;
 
 #ifdef TC_CGEN_MAX_RELAX
@@ -330,7 +391,7 @@ cgen_asm_finish_insn (insn, buf, length)
       
       /* Create a relaxable fragment for this instruction.  */
       old_frag = frag_now;
-      
+
       frag_var (rs_machine_dependent,
                max_len - byte_len /* max chars */,
                0 /* variable part already allocated */,
@@ -346,9 +407,15 @@ cgen_asm_finish_insn (insn, buf, length)
       old_frag->fr_cgen.insn    = insn;
       old_frag->fr_cgen.opindex = fixups[relax_operand].opindex;
       old_frag->fr_cgen.opinfo  = fixups[relax_operand].opinfo;
+      if (result)
+       result->frag = old_frag;
     }
   else
-    f = frag_more (byte_len);
+    {
+      f = frag_more (byte_len);
+      if (result)
+       result->frag = frag_now;
+    }
 
   /* If we're recording insns as numbers (rather than a string of bytes),
      target byte order handling is deferred until now.  */
@@ -377,10 +444,13 @@ cgen_asm_finish_insn (insn, buf, length)
   /* Create any fixups.  */
   for (i = 0; i < num_fixups; ++i)
     {
+      fixS * fixP;
+
       /* Don't create fixups for these.  That's done during relaxation.
         We don't need to test for CGEN_INSN_RELAX as they can't get here
         (see above).  */
-      if (CGEN_INSN_ATTR (insn, CGEN_INSN_RELAXABLE) != 0
+      if (relax_p
+         && CGEN_INSN_ATTR (insn, CGEN_INSN_RELAXABLE) != 0
          && CGEN_OPERAND_ATTR (& CGEN_SYM (operand_table) [fixups[i].opindex],
                                CGEN_OPERAND_RELAX) != 0)
        continue;
@@ -389,11 +459,19 @@ cgen_asm_finish_insn (insn, buf, length)
 #define md_cgen_record_fixup_exp cgen_record_fixup_exp
 #endif
 
-      md_cgen_record_fixup_exp (frag_now, f - frag_now->fr_literal,
-                               insn, length,
-                               & CGEN_SYM (operand_table) [fixups[i].opindex],
-                               fixups[i].opinfo,
-                               & fixups[i].exp);
+       fixP = md_cgen_record_fixup_exp (frag_now, f - frag_now->fr_literal,
+                                        insn, length,
+                                        & CGEN_SYM (operand_table) [fixups[i].opindex],
+                                        fixups[i].opinfo,
+                                        & fixups[i].exp);
+       if (result)
+         result->fixups[i] = fixP;
+    }
+
+  if (result)
+    {
+      result->num_fixups = num_fixups;
+      result->addr = f;
     }
 }
 
@@ -415,8 +493,8 @@ cgen_md_apply_fix3 (fixP, valueP, seg)
      valueT * valueP;
      segT     seg;
 {
-  char *      where = fixP->fx_frag->fr_literal + fixP->fx_where;
-  valueT      value;
+  char * where = fixP->fx_frag->fr_literal + fixP->fx_where;
+  valueT value;
 
   /* FIXME FIXME FIXME: The value we are passed in *valuep includes
      the symbol values.  Since we are using BFD_ASSEMBLER, if we are
@@ -447,7 +525,7 @@ cgen_md_apply_fix3 (fixP, valueP, seg)
            {
              /* We don't actually support subtracting a symbol.  */
              as_bad_where (fixP->fx_file, fixP->fx_line,
-                           "expression too complex");
+                           _("expression too complex"));
            }
        }
     }
@@ -468,14 +546,13 @@ cgen_md_apply_fix3 (fixP, valueP, seg)
             finish the job.  Testing for pcrel is a temporary hack.  */
          || fixP->fx_pcrel)
        {
-         /* This may seem like overkill, and using bfd_install_relocation or
-            some such may be preferable, but this is simple.  */
          CGEN_FIELDS_BITSIZE (& fields) = CGEN_INSN_BITSIZE (insn);
-         CGEN_SYM (set_operand) (opindex, & value, & fields);
-         errmsg = CGEN_SYM (validate_operand) (opindex, & fields);
+         CGEN_SYM (set_vma_operand) (opindex, & fields, (bfd_vma) value);
+         /* ??? 0 is passed for `pc' */
+         errmsg = CGEN_SYM (insert_operand) (opindex, & fields, where,
+                                             (bfd_vma) 0);
          if (errmsg)
-           as_warn_where (fixP->fx_file, fixP->fx_line, "%s\n", errmsg);
-         CGEN_SYM (insert_operand) (opindex, & fields, where);
+           as_warn_where (fixP->fx_file, fixP->fx_line, "%s", errmsg);
        }
 
       if (fixP->fx_done)
@@ -494,7 +571,7 @@ cgen_md_apply_fix3 (fixP, valueP, seg)
       else
        {
          as_bad_where (fixP->fx_file, fixP->fx_line,
-                       "unresolved expression that must be resolved");
+                       _("unresolved expression that must be resolved"));
          fixP->fx_done = 1;
          return 1;
        }
@@ -549,7 +626,7 @@ cgen_tc_gen_reloc (section, fixP)
   if (reloc->howto == (reloc_howto_type *) NULL)
     {
       as_bad_where (fixP->fx_file, fixP->fx_line,
-                   "internal error: can't export reloc type %d (`%s')",
+                   _("internal error: can't export reloc type %d (`%s')"),
                    fixP->fx_r_type, bfd_get_reloc_code_name (fixP->fx_r_type));
       return NULL;
     }
This page took 0.028053 seconds and 4 git commands to generate.