This is the mail archive of the cgen@sources.redhat.com mailing list for the CGEN project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Changes To Fixup Saving, Restoring and Swapping


Hi,

A port I'm working on requires packing a set of instructions (two at
this point, more later) into a vliw word.   In order to be able to
handle more than two instructions at a time during assembly, an
enhancement to the gas_cgen_[save/restore/swap]_fixups mechanism is
required. Currently this mechanism allows for one set of fixups to be
store then restored to/swapped with the current set.   I've made some
modifications so that fixup chains for many instructions can be stored
and selected from for restores and swaps.  Just in case it might be of
use, I've also added a little extra feature that allows for the current
fixups to be either kept or cleared when stored and for a set of stored
fixups to be either kept or cleared when restored.   I threw some
documentation in too.

Everything is still done essentially the way it was originally, only the
operations are preformed on the elements of an array, each of which
stores a fixup chain and a fixup count.

The only port that is affected by the changes is m32r .  I updated
tc-m32r.c to reflect the new calling inteface and ran the gas
testsuite.  There are no regressions.

The patch is attached.  Let me know if there are any comments or
objections. If there are none, I'll check it in in a day or so.

Thanks,

John Healy
Simulation Engineer
Red Hat
jhealy@redhat.com
[gas]

2001-07-05  John Healy  <jhealy@redhat.com>

        * cgen.c (gas_cgen_save_fixups): Modified to allow more than one
        set of fixups to be stored and to allow for the current set of
        fixups to be either saved or cleared.
        (gas_cgen_restore_fixups): Modified to allow the fixup chain to be
        restored to be chosen from any that are saved and for the stored
        fixups that have been restored to be either saved or cleared.
        (gas_cgen_swap_fixups): Modified to allow the current set of
        fixups to be swapped with any other set that has been saved.
        (gas_cgen_initialize_saved_fixups_array): New routine.
        * cgen.h: Modifed prototypes for gas_cgen_save_fixups,
        gas_cgen_restore_fixups, and gas_cgen_swap_fixups.  Added definitions
        for MAX_SAVED_FIXUP_CHAINS, KEEP_CURRENT, CLEAR_CURRENT,
        KEEP_STORED and CLEAR_STORED.
        * config/tc-m32r.c (assemble_two_insns): Changed calls to fixup
        store, swap and restore fuctions to reflect the new interface.

Index: gas/cgen.c
===================================================================
RCS file: /cvs/src/src/gas/cgen.c,v
retrieving revision 1.12
diff -c -3 -p -r1.12 cgen.c
*** cgen.c	2001/05/16 23:06:02	1.12
--- cgen.c	2001/07/05 16:32:04
*************** queue_fixup (opindex, opinfo, expP)
*** 94,155 ****
    ++ 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.  */
! /* ??? I think with cgen_asm_finish_insn (or something else) there is no
!    more need for this.  */
  
! static struct fixup saved_fixups[GAS_CGEN_MAX_FIXUPS];
! static int saved_num_fixups;
  
! void
! gas_cgen_save_fixups ()
  {
!   saved_num_fixups = num_fixups;
! 
!   memcpy (saved_fixups, fixups, sizeof (fixups[0]) * num_fixups);
! 
!   num_fixups = 0;
  }
  
! void
! gas_cgen_restore_fixups ()
  {
!   num_fixups = saved_num_fixups;
! 
!   memcpy (fixups, saved_fixups, sizeof (fixups[0]) * num_fixups);
  
!   saved_num_fixups = 0;
  }
  
! void
! gas_cgen_swap_fixups ()
  {
!   int tmp;
!   struct fixup tmp_fixup;
  
!   if (num_fixups == 0)
!     {
!       gas_cgen_restore_fixups ();
!     }
!   else if (saved_num_fixups == 0)
!     {
!       gas_cgen_save_fixups ();
!     }
!   else
!     {
!       tmp = saved_num_fixups;
!       saved_num_fixups = num_fixups;
!       num_fixups = tmp;
! 
!       for (tmp = GAS_CGEN_MAX_FIXUPS; tmp--;)
! 	{
! 	  tmp_fixup          = saved_fixups [tmp];
! 	  saved_fixups [tmp] = fixups [tmp];
! 	  fixups [tmp]       = tmp_fixup;
! 	}
      }
  }
  
--- 94,238 ----
    ++ num_fixups;
  }
  
! /* The following functions allow fixup chains to be stored, retrieved,
!    and swapped.  They are a generalization of a pre-existing scheme
!    for storing, restoring and swapping fixup chains that was used by
!    the m32r port.  The functionality is essentially the same, only
!    instead of only being able to store a single fixup chain, an entire
!    array of fixup chains can be stored.  It is the user's responsibility
!    to keep track of how many fixup chains have been stored and which
!    elements of the array they are in.
! 
!    The algorithms used are the same as in the old scheme with the
!    exception that an additional argument is taken by the save and
!    restore functions to allow the user to choose to keep or "wipe out"
!    the current or stored fixups, respectively.  If the choice is made
!    to wipe them out, then other than the array-ness of the whole thing,
!    the functionality is identical to the old scheme.
! 
!    gas_cgen_initialize_saved_fixups_array():
!       Sets num_fixups_in_chain to 0 for each element. Call this from
!       md_begin() if you plan to use these functions and you want the
!       fixup count in each element to be set to 0 intially.  This is
!       not necessary, but it's included just in case.  It performs
!       the same function for each element in the array of fixup chains
!       that gas_init_parse() performs for the current fixups.
! 
!    gas_cgen_save_fixups (element, current):
!       element - element number of the array you wish to store the fixups
!                 to.  No mechanism is build in for tracking what element
!                 was last stored to.
!       current - what to do with the current fixup count.  Should be either:
!                 KEEP_CURRENT (keep the current fixup count) or
!                 CLEAR_CURRENT (clear the current fixup count).
!       e.g.:     gas_cgen_save_fixups(0,CLEAR_CURRENT);
!                 stores the current fixups to the first element in the
!                 array and "wipes out" the current fixup count.  This
!                 is the same as the old gas_cgen_save_fixups().
! 
!    gas_cgen_restore_fixups (element, stored):
!       element - element number of the array you wish to restore the fixups
!                 from.
!       stored - what to do with the stored fixups after restoring them.
!                Should be either:
!                KEEP_STORED (leave the stored fixup count intact) or
!                CLEAR_STORED (clear the stored fixup count)
!       e.g.:    gas_cgen_restore_fixups(0,CLEAR_STORED);
!                restores the fixups from the first element in the
!                array and "wipes out" the stored fixup count in the
!                first element of the array.  This is the same as the
!                old gas_cgen_save_fixups().
! 
!    gas_cgen_swap_fixups(int element):
!        element - swap the current fixups with those in this element number.
!        e.g. gas_cgen_swap_fixups(0);
!             swaps the current fixups with those stored in element 0
!             of the array.  This is the same as the old gas_cgen_swap_fixups().
! */
! 
! struct saved_fixups {
!      struct fixup fixup_chain[GAS_CGEN_MAX_FIXUPS];
!      int num_fixups_in_chain;
! };
  
! static struct saved_fixups stored_fixups[MAX_SAVED_FIXUP_CHAINS];
  
! void gas_cgen_initialize_saved_fixups_array()
  {
!    int i = 0;
!    while (i < MAX_SAVED_FIXUP_CHAINS)
!       stored_fixups[i++].num_fixups_in_chain = 0;
  }
  
! void gas_cgen_save_fixups (int i, int current)
  {
!       if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS)
!       {
!           as_fatal("Index into stored_fixups[] out of bounds.");
!           return;
!       }
!       stored_fixups[i].num_fixups_in_chain = num_fixups;
!       memcpy(stored_fixups[i].fixup_chain, fixups,
!                     sizeof (fixups[0])*num_fixups);
!       if (current == CLEAR_CURRENT)
!          num_fixups = 0;
!       else if (current != KEEP_CURRENT)
!       {
!          /* Default is KEEP_CURRENT, but issue a warning. */
!          as_bad("save fixup not clearing current fixups.  Is that what you want?");
!       }
! }
  
! void gas_cgen_restore_fixups(int i, int stored)
! {
!       if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS)
!       {
!           as_fatal("Index into stored_fixups[] out of bounds.");
!           return;
!       }
!       num_fixups = stored_fixups[i].num_fixups_in_chain;
!       memcpy(fixups,stored_fixups[i].fixup_chain,
!                     (sizeof (stored_fixups[i].fixup_chain[0]))*num_fixups);
!       if (stored == CLEAR_STORED)
!          stored_fixups[i].num_fixups_in_chain = 0;
!       else if (stored != KEEP_STORED)
!       {
!          /* Default is KEEP_STORED, but issue a warning. */
!          as_bad("fixup restore not clearing stored fixups.  Is that what you want?");
!       }
  }
  
! void gas_cgen_swap_fixups(int i)
  {
!      int tmp;
!      struct fixup tmp_fixup;
  
!      if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS)
!      {
!          as_fatal("Index into stored_fixups[] out of bounds.");
!          return;
!      }
! 
!      if (num_fixups == 0)
!      {
!        gas_cgen_restore_fixups (i, CLEAR_STORED);
!      }
!      else if (stored_fixups[i].num_fixups_in_chain == 0)
!      {
!        gas_cgen_save_fixups (i, CLEAR_CURRENT);
!      }
!      else
!      {
!        tmp = stored_fixups[i].num_fixups_in_chain;
!        stored_fixups[i].num_fixups_in_chain = num_fixups;
!        num_fixups = tmp;
! 
!        for (tmp = GAS_CGEN_MAX_FIXUPS; tmp--;)
!        {
!          tmp_fixup          = stored_fixups[i].fixup_chain [tmp];
!          stored_fixups[i].fixup_chain[tmp] = fixups [tmp];
!          fixups [tmp]       = tmp_fixup;
!        }
      }
  }
  
Index: gas/cgen.h
===================================================================
RCS file: /cvs/src/src/gas/cgen.h,v
retrieving revision 1.7
diff -c -3 -p -r1.7 cgen.h
*** cgen.h	2001/03/08 23:24:22	1.7
--- cgen.h	2001/07/05 16:32:04
*************** extern const char * gas_cgen_parse_opera
*** 53,61 ****
  /* Call this from md_assemble to initialize the assembler callback.  */
  extern void gas_cgen_init_parse PARAMS ((void));
  
! extern void gas_cgen_save_fixups PARAMS ((void));
! extern void gas_cgen_restore_fixups PARAMS ((void));
! extern void gas_cgen_swap_fixups PARAMS ((void));
  
  /* Add a register to the assembler's hash table.
     This makes lets GAS parse registers for us.
--- 53,69 ----
  /* Call this from md_assemble to initialize the assembler callback.  */
  extern void gas_cgen_init_parse PARAMS ((void));
  
! /* Routines and macros for saving fixup chains. */
! extern void gas_cgen_save_fixups PARAMS ((int,int));
! extern void gas_cgen_restore_fixups PARAMS ((int,int));
! extern void gas_cgen_swap_fixups PARAMS ((int));
! extern void gas_cgen_initialize_saved_fixups_array PARAMS ((void));
! #define MAX_SAVED_FIXUP_CHAINS 50
! #define KEEP_CURRENT 0
! #define CLEAR_CURRENT 1
! #define KEEP_STORED 0
! #define CLEAR_STORED 1
! 
  
  /* Add a register to the assembler's hash table.
     This makes lets GAS parse registers for us.
Index: gas/config/tc-m32r.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-m32r.c,v
retrieving revision 1.19
diff -c -3 -p -r1.19 tc-m32r.c
*** tc-m32r.c	2001/05/10 11:32:51	1.19
--- tc-m32r.c	2001/07/05 16:32:05
*************** md_begin ()
*** 554,559 ****
--- 554,561 ----
    scom_symbol.section         = &scom_section;
  
    allow_m32rx (enable_m32rx);
+ 
+   gas_cgen_initialize_saved_fixups_array();
  }
  
  #define OPERAND_IS_COND_BIT(operand, indices, index) \
*************** assemble_two_insns (str, str2, parallel_
*** 832,838 ****
  
    /* Preserve any fixups that have been generated and reset the list
       to empty.  */
!   gas_cgen_save_fixups ();
  
    /* Get the indices of the operands of the instruction.  */
    /* FIXME: CGEN_FIELDS is already recorded, but relying on that fact
--- 834,840 ----
  
    /* Preserve any fixups that have been generated and reset the list
       to empty.  */
!   gas_cgen_save_fixups (0,CLEAR_CURRENT);
  
    /* Get the indices of the operands of the instruction.  */
    /* FIXME: CGEN_FIELDS is already recorded, but relying on that fact
*************** assemble_two_insns (str, str2, parallel_
*** 941,947 ****
        || (errmsg = (char *) can_make_parallel (&first, &second)) == NULL)
      {
        /* Get the fixups for the first instruction.  */
!       gas_cgen_swap_fixups ();
  
        /* Write it out.  */
        expand_debug_syms (first.debug_sym_link, 1);
--- 943,949 ----
        || (errmsg = (char *) can_make_parallel (&first, &second)) == NULL)
      {
        /* Get the fixups for the first instruction.  */
!       gas_cgen_swap_fixups (0);
  
        /* Write it out.  */
        expand_debug_syms (first.debug_sym_link, 1);
*************** assemble_two_insns (str, str2, parallel_
*** 953,959 ****
  	make_parallel (second.buffer);
  
        /* Get its fixups.  */
!       gas_cgen_restore_fixups ();
  
        /* Write it out.  */
        expand_debug_syms (second.debug_sym_link, 1);
--- 955,961 ----
  	make_parallel (second.buffer);
  
        /* Get its fixups.  */
!       gas_cgen_restore_fixups (0, CLEAR_STORED);
  
        /* Write it out.  */
        expand_debug_syms (second.debug_sym_link, 1);
*************** assemble_two_insns (str, str2, parallel_
*** 972,978 ****
        make_parallel (first.buffer);
  
        /* Get the fixups for the first instruction.  */
!       gas_cgen_restore_fixups ();
  
        /* Write out the first instruction.  */
        expand_debug_syms (first.debug_sym_link, 1);
--- 974,980 ----
        make_parallel (first.buffer);
  
        /* Get the fixups for the first instruction.  */
!       gas_cgen_restore_fixups (0, CLEAR_STORED);
  
        /* Write out the first instruction.  */
        expand_debug_syms (first.debug_sym_link, 1);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]