Add support for parallel instructions.
authorNick Clifton <nickc@redhat.com>
Thu, 15 Jan 1998 01:58:34 +0000 (01:58 +0000)
committerNick Clifton <nickc@redhat.com>
Thu, 15 Jan 1998 01:58:34 +0000 (01:58 +0000)
gas/ChangeLog
gas/cgen.c
gas/config/tc-m32r.c

index b83f30e641e4fbaccc349e830ef7a4387a008408..4d540a86bebabd1040b5ce550796df2a093a141a 100644 (file)
@@ -1,3 +1,9 @@
+Wed Jan 14 17:52:33 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * config/tc-m32r.c (md_assemble): Add support for parsing parallel
+       instructions.
+       * cgen.c: Formatting changes to improve readability.
+
 Wed Jan 14 15:41:41 1998  Jeffrey A Law  (law@cygnus.com)
 
        * config/tc-mips.c (macro): Rework division code to avoid unfilled
index 0e5c33c4acba300168263d6e6ef9a17ed96e09c3..d65526d993293b5680765c3ef168ac10c537fe69 100644 (file)
@@ -30,13 +30,13 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
 
 void
 cgen_asm_record_register (name, number)
-     char *name;
-     int number;
+     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.  */
   symbol_table_insert (symbol_create (name, reg_section,
-                                     number, &zero_address_frag));
+                                     number, & zero_address_frag));
 }
 
 /* We need to keep a list of fixups.  We can't simply generate them as
@@ -52,15 +52,15 @@ 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 [MAX_FIXUPS];
+static int          num_fixups;
 
 /* Prepare to parse an instruction.
    ??? May wish to make this static and delete calls in md_assemble.  */
@@ -75,16 +75,16 @@ cgen_asm_init_parse ()
 
 void
 cgen_queue_fixup (opindex, opinfo, expP)
-     int opindex;
-     expressionS *expP;
+     int           opindex;
+     expressionS * expP;
 {
   /* We need to generate a fixup for this expression.  */
   if (num_fixups >= MAX_FIXUPS)
     as_fatal ("too many fixups");
-  fixups[num_fixups].exp = *expP;
+  fixups[num_fixups].exp     = * expP;
   fixups[num_fixups].opindex = opindex;
-  fixups[num_fixups].opinfo = opinfo;
-  ++num_fixups;
+  fixups[num_fixups].opinfo  = opinfo;
+  ++ num_fixups;
 }
 
 /* Default routine to record a fixup.
@@ -102,16 +102,16 @@ cgen_queue_fixup (opindex, opinfo, expP)
 
 fixS *
 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;
+     fragS *              frag;
+     int                  where;
+     const CGEN_INSN *    insn;
+     int                  length;
+     const CGEN_OPERAND * operand;
+     int                  opinfo;
+     symbolS *            symbol;
+     offsetT              offset;
 {
-  fixS *fixP;
+  fixS * fixP;
 
   /* It may seem strange to use operand->attrs and not insn->attrs here,
      but it is the operand that has a pc relative relocation.  */
@@ -119,7 +119,7 @@ cgen_record_fixup (frag, where, insn, length, operand, opinfo, symbol, offset)
   fixP = fix_new (frag, where, length / 8, symbol, offset,
                  CGEN_OPERAND_ATTR (operand, CGEN_OPERAND_PCREL_ADDR) != 0,
                  (bfd_reloc_code_real_type) ((int) BFD_RELOC_UNUSED + CGEN_OPERAND_INDEX (operand)));
-  fixP->tc_fix_data.insn = (PTR) insn;
+  fixP->tc_fix_data.insn   = (PTR) insn;
   fixP->tc_fix_data.opinfo = opinfo;
 
   return fixP;
@@ -140,15 +140,15 @@ cgen_record_fixup (frag, where, insn, length, operand, opinfo, symbol, offset)
 
 fixS *
 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;
+     fragS *              frag;
+     int                  where;
+     const CGEN_INSN *    insn;
+     int                  length;
+     const CGEN_OPERAND * operand;
+     int                  opinfo;
+     expressionS *        exp;
 {
-  fixS *fixP;
+  fixS * fixP;
 
   /* It may seem strange to use operand->attrs and not insn->attrs here,
      but it is the operand that has a pc relative relocation.  */
@@ -178,23 +178,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_result *resultP;
-     bfd_vma *valueP;
+     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 is volatile to survive the setjmp.  */
-  char * volatile hold;
+  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)
     {
@@ -204,20 +204,20 @@ cgen_parse_operand (want, strP, opindex, opinfo, resultP, valueP)
 
   resultP_1 = resultP;
   hold = input_line_pointer;
-  input_line_pointer = (char *) *strP;
+  input_line_pointer = (char *) * strP;
 
   /* We rely on md_operand to longjmp back to us.
      This is done via cgen_md_operand.  */
   if (setjmp (expr_jmp_buf) != 0)
     {
       input_line_pointer = (char *) hold;
-      *resultP_1 = CGEN_PARSE_OPERAND_RESULT_ERROR;
+      * resultP_1 = CGEN_PARSE_OPERAND_RESULT_ERROR;
       return "illegal operand";
     }
 
-  expression (&exp);
+  expression (& exp);
 
-  *strP = input_line_pointer;
+  * strP = input_line_pointer;
   input_line_pointer = hold;
 
   /* FIXME: Need to check `want'.  */
@@ -226,24 +226,24 @@ cgen_parse_operand (want, strP, opindex, opinfo, resultP, valueP)
     {
     case O_illegal :
       errmsg = "illegal operand";
-      *resultP = CGEN_PARSE_OPERAND_RESULT_ERROR;
+      * resultP = CGEN_PARSE_OPERAND_RESULT_ERROR;
       break;
     case O_absent :
       errmsg = "missing operand";
-      *resultP = CGEN_PARSE_OPERAND_RESULT_ERROR;
+      * resultP = CGEN_PARSE_OPERAND_RESULT_ERROR;
       break;
     case O_constant :
-      *valueP = exp.X_add_number;
-      *resultP = CGEN_PARSE_OPERAND_RESULT_NUMBER;
+      * valueP = exp.X_add_number;
+      * resultP = CGEN_PARSE_OPERAND_RESULT_NUMBER;
       break;
     case O_register :
-      *valueP = exp.X_add_number;
-      *resultP = CGEN_PARSE_OPERAND_RESULT_REGISTER;
+      * valueP = exp.X_add_number;
+      * resultP = CGEN_PARSE_OPERAND_RESULT_REGISTER;
       break;
     default :
-      cgen_queue_fixup (opindex, opinfo, &exp);
-      *valueP = 0;
-      *resultP = CGEN_PARSE_OPERAND_RESULT_QUEUED;
+      cgen_queue_fixup (opindex, opinfo, & exp);
+      * valueP = 0;
+      * resultP = CGEN_PARSE_OPERAND_RESULT_QUEUED;
       break;
     }
 
@@ -257,7 +257,7 @@ cgen_parse_operand (want, strP, opindex, opinfo, resultP, valueP)
 
 void
 cgen_md_operand (expressionP)
-     expressionS *expressionP;
+     expressionS * expressionP;
 {
   longjmp (expr_jmp_buf, 1);
 }
@@ -268,12 +268,13 @@ cgen_md_operand (expressionP)
 
 void
 cgen_asm_finish_insn (insn, buf, length)
-     const CGEN_INSN *insn;
-     cgen_insn_t *buf;
-     unsigned int length;
+     const CGEN_INSN * insn;
+     cgen_insn_t *     buf;
+     unsigned int      length;
 {
-  int i, 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
@@ -299,7 +300,7 @@ cgen_asm_finish_insn (insn, buf, length)
       /* Scan the fixups for the operand affected by relaxing
         (i.e. the branch address).  */
 
-      for (i = 0; i < num_fixups; ++i)
+      for (i = 0; i < num_fixups; ++ i)
        {
          if (CGEN_OPERAND_ATTR (& CGEN_SYM (operand_table) [fixups[i].opindex],
                                 CGEN_OPERAND_RELAX) != 0)
@@ -312,8 +313,8 @@ cgen_asm_finish_insn (insn, buf, length)
 
   if (relax_operand != -1)
     {
-      int max_len;
-      fragS *old_frag;
+      int     max_len;
+      fragS * old_frag;
 
 #ifdef TC_CGEN_MAX_RELAX
       max_len = TC_CGEN_MAX_RELAX (insn, byte_len);
@@ -323,10 +324,13 @@ cgen_asm_finish_insn (insn, buf, length)
       /* Ensure variable part and fixed part are in same fragment.  */
       /* FIXME: Having to do this seems like a hack.  */
       frag_grow (max_len);
+      
       /* Allocate space for the fixed part.  */
       f = frag_more (byte_len);
+      
       /* 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 */,
@@ -336,11 +340,12 @@ cgen_asm_finish_insn (insn, buf, length)
                fixups[relax_operand].exp.X_add_symbol,
                fixups[relax_operand].exp.X_add_number,
                f);
+      
       /* Record the operand number with the fragment so md_convert_frag
         can use cgen_md_record_fixup to record the appropriate reloc.  */
-      old_frag->fr_cgen.insn = insn;
+      old_frag->fr_cgen.insn    = insn;
       old_frag->fr_cgen.opindex = fixups[relax_operand].opindex;
-      old_frag->fr_cgen.opinfo = fixups[relax_operand].opinfo;
+      old_frag->fr_cgen.opinfo  = fixups[relax_operand].opinfo;
     }
   else
     f = frag_more (byte_len);
@@ -352,15 +357,15 @@ cgen_asm_finish_insn (insn, buf, length)
     {
     case 16:
       if (cgen_big_endian_p)
-       bfd_putb16 ((bfd_vma) *buf, f);
+       bfd_putb16 ((bfd_vma) * buf, f);
       else
-       bfd_putl16 ((bfd_vma) *buf, f);
+       bfd_putl16 ((bfd_vma) * buf, f);
       break;
     case 32:
       if (cgen_big_endian_p)
-       bfd_putb32 ((bfd_vma) *buf, f);
+       bfd_putb32 ((bfd_vma) * buf, f);
       else
-       bfd_putl32 ((bfd_vma) *buf, f);
+       bfd_putl32 ((bfd_vma) * buf, f);
       break;
     default:
       abort ();
@@ -388,7 +393,7 @@ cgen_asm_finish_insn (insn, buf, length)
                                insn, length,
                                & CGEN_SYM (operand_table) [fixups[i].opindex],
                                fixups[i].opinfo,
-                               &fixups[i].exp);
+                               & fixups[i].exp);
     }
 }
 
@@ -406,12 +411,12 @@ cgen_asm_finish_insn (insn, buf, length)
 
 int
 cgen_md_apply_fix3 (fixP, valueP, seg)
-     fixS *fixP;
-     valueT *valueP;
-     segT seg;
+     fixS *   fixP;
+     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
@@ -426,11 +431,11 @@ cgen_md_apply_fix3 (fixP, valueP, seg)
 
   if (fixP->fx_addsy == (symbolS *) NULL)
     {
-      value = *valueP;
+      value = * valueP;
       fixP->fx_done = 1;
     }
   else if (fixP->fx_pcrel)
-    value = *valueP;
+    value = * valueP;
   else
     {
       value = fixP->fx_offset;
@@ -449,12 +454,12 @@ cgen_md_apply_fix3 (fixP, valueP, seg)
 
   if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
     {
-      int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
-      const CGEN_OPERAND *operand = & CGEN_SYM (operand_table) [opindex];
-      const char *errmsg;
+      int                      opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
+      const CGEN_OPERAND *     operand = & CGEN_SYM (operand_table) [opindex];
+      const char *             errmsg;
       bfd_reloc_code_real_type reloc_type;
-      CGEN_FIELDS fields;
-      const CGEN_INSN *insn = (CGEN_INSN *) fixP->tc_fix_data.insn;
+      CGEN_FIELDS              fields;
+      const CGEN_INSN *        insn = (CGEN_INSN *) fixP->tc_fix_data.insn;
 
       /* If the reloc has been fully resolved finish the operand here.  */
       /* FIXME: This duplicates the capabilities of code in BFD.  */
@@ -465,12 +470,12 @@ cgen_md_apply_fix3 (fixP, valueP, seg)
        {
          /* 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_FIELDS_BITSIZE (& fields) = CGEN_INSN_BITSIZE (insn);
+         CGEN_SYM (set_operand) (opindex, & value, & fields);
+         errmsg = CGEN_SYM (validate_operand) (opindex, & fields);
          if (errmsg)
            as_warn_where (fixP->fx_file, fixP->fx_line, "%s\n", errmsg);
-         CGEN_SYM (insert_operand) (opindex, &fields, where);
+         CGEN_SYM (insert_operand) (opindex, & fields, where);
        }
 
       if (fixP->fx_done)
@@ -533,10 +538,10 @@ cgen_md_apply_fix3 (fixP, valueP, seg)
 
 arelent *
 cgen_tc_gen_reloc (section, fixP)
-     asection *section;
-     fixS *fixP;
+     asection * section;
+     fixS *     fixP;
 {
-  arelent *reloc;
+  arelent * reloc;
 
   reloc = (arelent *) bfd_alloc (stdoutput, sizeof (arelent));
 
@@ -551,9 +556,9 @@ cgen_tc_gen_reloc (section, fixP)
 
   assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
 
-  reloc->sym_ptr_ptr = &fixP->fx_addsy->bsym;
-  reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
-  reloc->addend = fixP->fx_addnumber;
+  reloc->sym_ptr_ptr = & fixP->fx_addsy->bsym;
+  reloc->address     = fixP->fx_frag->fr_address + fixP->fx_where;
+  reloc->addend      = fixP->fx_addnumber;
 
   return reloc;
 }
index 466da213247abdbb52366fed32c2c2a3652706a5..5053eac095343eeb1fcaf0a649f97faf2b6932f4 100644 (file)
 #include "subsegs.h"     
 #include "cgen-opc.h"
 
+#include "../../opcodes/m32r-asm.c"
+#include "../../opcodes/m32r-asm.in"
+
 /* Non-null if last insn was a 16 bit insn on a 32 bit boundary
    (i.e. was the first of two 16 bit insns).  */
-static const CGEN_INSN *prev_insn = NULL;
+static const CGEN_INSN * prev_insn = NULL;
 
 /* Non-zero if we've seen a relaxable insn since the last 32 bit
    alignment request.  */
@@ -40,25 +43,24 @@ static int m32r_relax;
 
 /* If non-NULL, pointer to cpu description file to read.
    This allows runtime additions to the assembler.  */
-static char *m32r_cpu_desc;
+static char * m32r_cpu_desc;
 
 /* start-sanitize-m32rx */
 /* Non-zero if -m32rx has been specified, in which case support for the
    extended M32RX instruction set should be enabled.  */
-/* Indicates the target BFD machine number.  */
 static int enable_m32rx = 0;
 /* end-sanitize-m32rx */
 
 /* stuff for .scomm symbols.  */
-static segT sbss_section;
+static segT     sbss_section;
 static asection scom_section;
-static asymbol scom_symbol;
+static asymbol  scom_symbol;
 
-const char comment_chars[] = ";";
-const char line_comment_chars[] = "#";
+const char comment_chars[]        = ";";
+const char line_comment_chars[]   = "#";
 const char line_separator_chars[] = "";
-const char EXP_CHARS[] = "eE";
-const char FLT_CHARS[] = "dD";
+const char EXP_CHARS[]            = "eE";
+const char FLT_CHARS[]            = "dD";
 
 /* Relocations against symbols are done in two
    parts, with a HI relocation and a LO relocation.  Each relocation
@@ -73,17 +75,15 @@ const char FLT_CHARS[] = "dD";
 
 struct m32r_hi_fixup
 {
-  /* Next HI fixup.  */
-  struct m32r_hi_fixup *next;
-  /* This fixup.  */
-  fixS *fixp;
-  /* The section this fixup is in.  */
-  segT seg;
+  struct m32r_hi_fixup * next;  /* Next HI fixup.  */
+  fixS *                 fixp;  /* This fixup.  */
+  segT                   seg;   /* The section this fixup is in.  */
+
 };
 
 /* The list of unmatched HI relocs.  */
 
-static struct m32r_hi_fixup *m32r_hi_fixup_list;
+static struct m32r_hi_fixup * m32r_hi_fixup_list;
 
 static void m32r_record_hi16 PARAMS ((int, fixS *, segT seg));
 
@@ -95,11 +95,12 @@ allow_m32rx (int on)
   enable_m32rx = on;
 
   if (stdoutput != NULL)
-    bfd_set_arch_mach (stdoutput, TARGET_ARCH, enable_m32rx ? bfd_mach_m32rx : bfd_mach_m32r);
+    bfd_set_arch_mach (stdoutput, TARGET_ARCH,
+                      enable_m32rx ? bfd_mach_m32rx : bfd_mach_m32r);
 }
 /* end-sanitize-m32rx */
 \f
-const char *md_shortopts = "";
+const char * md_shortopts = "";
 
 struct option md_longopts[] =
 {
@@ -117,12 +118,12 @@ struct option md_longopts[] =
 
   {NULL, no_argument, NULL, 0}
 };
-size_t md_longopts_size = sizeof(md_longopts);       
+size_t md_longopts_size = sizeof (md_longopts);
 
 int
 md_parse_option (c, arg)
-     int c;
-     char *arg;
+     int    c;
+     char * arg;
 {
   switch (c)
     {
@@ -148,7 +149,7 @@ md_parse_option (c, arg)
 
 void
 md_show_usage (stream)
-  FILE *stream;
+  FILE * stream;
 {
   fprintf (stream, "M32R/X options:\n");
 /* start-sanitize-m32rx */
@@ -195,12 +196,12 @@ const pseudo_typeS md_pseudo_table[] =
 
 int
 m32r_do_align (n, fill, len, max)
-     int n;
-     const char *fill;
-     int len;
-     int max;
+     int          n;
+     const char * fill;
+     int          len;
+     int          max;
 {
-  if ((fill == NULL || (*fill == 0 && len == 1))
+  if ((fill == NULL || (* fill == 0 && len == 1))
       && (now_seg->flags & SEC_CODE) != 0
       /* Only do this special handling if aligning to at least a
         4 byte boundary.  */
@@ -224,7 +225,8 @@ m32r_do_align (n, fill, len, max)
         nops.  */
       if (n > 2)
        {
-         static const unsigned char multi_nop_pattern[] = { 0x70, 0x00, 0xf0, 0x00 };
+         static const unsigned char multi_nop_pattern[] =
+         { 0x70, 0x00, 0xf0, 0x00 };
          frag_align_pattern (n, multi_nop_pattern, sizeof multi_nop_pattern,
                              max ? max - 2 : 0);
        }
@@ -238,7 +240,7 @@ static void
 assemble_nop (opcode)
      int opcode;
 {
-  char *f = frag_more (2);
+  char * f = frag_more (2);
   md_number_to_chars (f, opcode, 2);
 }
 
@@ -269,17 +271,21 @@ int
 m32r_fill_insn (done)
      int done;
 {
-  segT seg;
+  segT    seg;
   subsegT subseg;
 
   if (prev_seg != NULL)
     {
-      seg = now_seg;
+      seg    = now_seg;
       subseg = now_subseg;
+      
       subseg_set (prev_seg, prev_subseg);
+      
       fill_insn (0);
+      
       subseg_set (seg, subseg);
     }
+  
   return 1;
 }
 \f
@@ -287,22 +293,24 @@ void
 md_begin ()
 {
   flagword applicable;
-  segT seg;
-  subsegT subseg;
+  segT     seg;
+  subsegT  subseg;
 
   /* Initialize the `cgen' interface.  */
 
   /* This is a callback from cgen to gas to parse operands.  */
   cgen_parse_operand_fn = cgen_parse_operand;
+  
   /* Set the machine number and endian.  */
   CGEN_SYM (init_asm) (0 /* mach number */,
-                      target_big_endian ? CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE);
+                      target_big_endian ?
+                      CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE);
 
 #if 0 /* not supported yet */
   /* If a runtime cpu description file was provided, parse it.  */
   if (m32r_cpu_desc != NULL)
     {
-      const char *errmsg;
+      const char * errmsg;
 
       errmsg = cgen_read_cpu_file (m32r_cpu_desc);
       if (errmsg != NULL)
@@ -311,15 +319,17 @@ md_begin ()
 #endif
 
   /* Save the current subseg so we can restore it [it's the default one and
-     we don't want the initial section to be .sbss.  */
-  seg = now_seg;
+     we don't want the initial section to be .sbss].  */
+  seg    = now_seg;
   subseg = now_subseg;
 
   /* The sbss section is for local .scomm symbols.  */
   sbss_section = subseg_new (".sbss", 0);
+  
   /* This is copied from perform_an_assembly_pass.  */
   applicable = bfd_applicable_section_flags (stdoutput);
   bfd_set_section_flags (stdoutput, sbss_section, applicable & SEC_ALLOC);
+  
 #if 0 /* What does this do? [see perform_an_assembly_pass]  */
   seg_info (bss_section)->bss = 1;
 #endif
@@ -328,51 +338,221 @@ md_begin ()
 
   /* We must construct a fake section similar to bfd_com_section
      but with the name .scommon.  */
-  scom_section = bfd_com_section;
-  scom_section.name = ".scommon";
-  scom_section.output_section = &scom_section;
-  scom_section.symbol = &scom_symbol;
-  scom_section.symbol_ptr_ptr = &scom_section.symbol;
-  scom_symbol = *bfd_com_section.symbol;
-  scom_symbol.name = ".scommon";
-  scom_symbol.section = &scom_section;
+  scom_section                = bfd_com_section;
+  scom_section.name           = ".scommon";
+  scom_section.output_section = & scom_section;
+  scom_section.symbol         = & scom_symbol;
+  scom_section.symbol_ptr_ptr = & scom_section.symbol;
+  scom_symbol                 = * bfd_com_section.symbol;
+  scom_symbol.name            = ".scommon";
+  scom_symbol.section         = & scom_section;
 
 /* start-sanitize-m32rx */
   allow_m32rx (enable_m32rx);
 /* end-sanitize-m32rx */
 }
 
+/* Returns non zero if the given instruction writes to a destination register.  */
+static int
+writes_to_dest_reg (insn)
+     const CGEN_INSN * insn;
+{
+  unsigned char * syntax = CGEN_SYNTAX_STRING (CGEN_INSN_SYNTAX (insn));
+  unsigned char   c;
+  
+  /* Scan the syntax string looking for a destination register.  */
+  while ((c = (* syntax ++)) != 0)
+    if (c == 128 + M32R_OPERAND_DR)
+      break;
+
+  return c;
+}
+
+/* Returns an integer representing the destination register of
+   the given insn, or -1 if the insn has no destination.  */
+static int
+get_dest_reg (insn)
+     const CGEN_INSN * insn;
+{
+  /* XXX to be done.  */
+  return -1;
+}
+
 void
 md_assemble (str)
-     char *str;
+     char * str;
 {
 #ifdef CGEN_INT_INSN
-  cgen_insn_t buffer[CGEN_MAX_INSN_SIZE / sizeof (cgen_insn_t)];
+  cgen_insn_t              buffer [CGEN_MAX_INSN_SIZE / sizeof (cgen_insn_t)];
+  cgen_insn_t              prev_buffer [CGEN_MAX_INSN_SIZE / sizeof (cgen_insn_t)];
 #else
-  char buffer[CGEN_MAX_INSN_SIZE];
+  char                     buffer [CGEN_MAX_INSN_SIZE];
+  char                     prev_buffer [CGEN_MAX_INSN_SIZE];
 #endif
-  CGEN_FIELDS fields;
-  const CGEN_INSN *insn;
-  char *errmsg;
-
+  CGEN_FIELDS              fields;
+  CGEN_FIELDS              prev_fields;
+  const CGEN_INSN *        insn;
+  char *                   errmsg;
+  char *                   str2 = NULL;
+  int                     is_parallel = false;
+  
   /* Initialize GAS's cgen interface for a new instruction.  */
   cgen_asm_init_parse ();
 
-  insn = CGEN_SYM (assemble_insn) (str, &fields, buffer, &errmsg);
+  /* Look for a parallel instruction seperator.  */
+  if ((str2 = strstr (str, "||")) != NULL)
+    {
+      char * str3;
+      
+      * str2 = 0; /* Seperate the two instructions.  */
+
+      /* If there was a previous 16 bit insn, then fill the following 16 bit slot,
+        so that the parallel instruction will start on a 32 bit boundary.  */
+      if (prev_insn)
+       fill_insn (0);
+
+      /* Assemble the first instruction.  */
+      prev_insn = CGEN_SYM (assemble_insn) (str, & prev_fields, prev_buffer, & errmsg);
+      if (! prev_insn)
+       {
+         as_bad (errmsg);
+         return;
+       }
+
+      /* Check to see if this is an allowable parallel insn.  */
+      if (CGEN_INSN_ATTR (prev_insn, CGEN_INSN_PIPE) == PIPE_NONE)
+       {
+         as_bad ("instruction '%s' cannot be executed in parallel.", str);
+         return;
+       }
+       
+/* start-sanitize-m32rx */
+      if (! enable_m32rx && 
+         CGEN_INSN_ATTR (prev_insn, CGEN_INSN_MACH) == MACH_M32RX)
+       {
+         as_bad ("instruction '%s' is for the M32RX only", str);
+         return;
+       }
+/* end-sanitize-m32rx */
+  
+      /* fixups = fixups->next; */
+
+      *str2 = '|';       /* Restore the original assembly text, just in case it is needed.  */
+      str3  = str;       /* Save the original string pointer.  */
+      str   = str2 + 2;  /* Advanced past the parsed string.  */
+      str2  = str3;      /* Remember the entire string in case it is needed for error messages.  */
+
+      is_parallel = true;
+    }
+  
+  insn = CGEN_SYM (assemble_insn) (str, & fields, buffer, & errmsg);
   if (!insn)
     {
       as_bad (errmsg);
       return;
     }
 
-  if (CGEN_INSN_BITSIZE (insn) == 32)
+/* start-sanitize-m32rx */
+  if (! enable_m32rx
+      && CGEN_INSN_ATTR (insn, CGEN_INSN_MACH) == (1 << MACH_M32RX))
+    {
+      as_bad ("instruction '%s' is for the M32RX only", str);
+      return;
+    }
+/* end-sanitize-m32rx */
+  
+  if (is_parallel)
+    {
+/* start-sanitize-m32rx */
+      if (! enable_m32rx)
+       {
+         if (strcmp (prev_insn->name, "nop") != 0
+             && strcmp (insn->name, "nop") != 0)
+           {
+             as_bad ("'%s': only the NOP instruction can be issued in parallel on the m32r", str2);
+             return;
+           }
+       }
+/* end-sanitize-m32rx */
+      
+      /* Check to see if this is an allowable parallel insn.  */
+      if (CGEN_INSN_ATTR (insn, CGEN_INSN_PIPE) == PIPE_NONE)
+       {
+         as_bad ("instruction '%s', cannot be executed in parallel.", str);
+         return;
+       }
+
+      /* Check to see that the two instructions can be placed in parallel. */
+      if ((CGEN_INSN_ATTR (insn, CGEN_INSN_PIPE) == CGEN_INSN_ATTR (prev_insn, CGEN_INSN_PIPE))
+         && (CGEN_INSN_ATTR (insn, CGEN_INSN_PIPE) != PIPE_OS))
+       {
+         as_bad ("'%s': both instructions use the same execution pipeline", str2);
+         return;
+       }
+#if 0
+      /* Check that the instructions do not write to the same destination register.  */
+      if (writes_to_dest_reg (insn)
+         && writes_to_dest_reg (prev_insn) /* This test is actually redundant.  */
+         && get_dest_reg (insn) == get_dest_reg (prev_insn))
+       {
+         as_bad ("'%s': both instructions write to the same destination register", str2);
+         return;
+       }
+#endif
+      
+      /* Force the top bit of the second insn to be set.  */
+#if 0 /*def CGEN_INT_INSN*/
+#define MAKE_PARALLEL(insn)    ((insn) |= 0x8000)
+      switch (CGEN_FIELDS_BITSIZE (& fields))
+       {
+         bfd_vma value;
+         
+       case 16:
+         if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG)
+           {
+             value = bfd_getb16 ((bfd_vma) * buffer);
+             MAKE_PARALLEL (value);
+             bfd_putb16 (value, buffer);
+           }
+         else
+           {
+             value = bfd_getl16 ((bfd_vma) * buffer);
+             MAKE_PARALLEL (value);
+             bfd_putl16 (value, buffer);
+           }
+         break;
+       default:
+         abort ();
+       }
+#else
+#define MAKE_PARALLEL(insn)    ((insn) |= 0x80)
+      MAKE_PARALLEL (buffer [CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG ? 0 : 1]);
+#endif
+      
+      /* Generate the parallel instructions */
+      cgen_asm_finish_insn (prev_insn, prev_buffer, CGEN_FIELDS_BITSIZE (& prev_fields));
+      cgen_asm_finish_insn (insn, buffer, CGEN_FIELDS_BITSIZE (& fields));
+
+      /* If prev_ins is relaxable (and insn is not), then swap them, so that the test
+        after the end of this if-then-else section will work.  */
+      if (CGEN_INSN_ATTR (prev_insn, CGEN_INSN_RELAXABLE))
+       insn = prev_insn;
+      
+      /* Clear the prev_insn variable, since it only used if the insn was the first
+        16 bit insn in a 32 bit word.  */
+      prev_insn = NULL;
+    }
+  else if (CGEN_INSN_BITSIZE (insn) == 32)
     {
       /* 32 bit insns must live on 32 bit boundaries.  */
-      /* FIXME: If calling fill_insn too many times turns us into a memory
-        pig, can we call assemble_nop instead of !seen_relaxable_p?  */
       if (prev_insn || seen_relaxable_p)
-       fill_insn (0);
-      cgen_asm_finish_insn (insn, buffer, CGEN_FIELDS_BITSIZE (&fields));
+       {
+         /* FIXME: If calling fill_insn too many times turns us into a memory
+            pig, can we call assemble_nop instead of !seen_relaxable_p?  */
+         fill_insn (0);
+       }
+      
+      cgen_asm_finish_insn (insn, buffer, CGEN_FIELDS_BITSIZE (& fields));
     }
   else
     {
@@ -382,7 +562,8 @@ md_assemble (str)
        prev_insn = NULL;
       else
        prev_insn = insn;
-      cgen_asm_finish_insn (insn, buffer, CGEN_FIELDS_BITSIZE (&fields));
+      
+      cgen_asm_finish_insn (insn, buffer, CGEN_FIELDS_BITSIZE (& fields));
 
       /* If the insn needs the following one to be on a 32 bit boundary
         (e.g. subroutine calls), fill this insn's slot.  */
@@ -398,7 +579,7 @@ md_assemble (str)
     seen_relaxable_p = 1;
 
   /* Set these so m32r_fill_insn can use them.  */
-  prev_seg = now_seg;
+  prev_seg    = now_seg;
   prev_subseg = now_subseg;
 }
 
@@ -407,18 +588,18 @@ md_assemble (str)
 
 void 
 md_operand (expressionP)
-     expressionS *expressionP;
+     expressionS * expressionP;
 {
-  if (*input_line_pointer == '#')
+  if (* input_line_pointer == '#')
     {
-      input_line_pointer++;
+      input_line_pointer ++;
       expression (expressionP);
     }
 }
 
 valueT
 md_section_align (segment, size)
-     segT segment;
+     segT   segment;
      valueT size;
 {
   int align = bfd_get_section_alignment (stdoutput, segment);
@@ -427,7 +608,7 @@ md_section_align (segment, size)
 
 symbolS *
 md_undefined_symbol (name)
-  char *name;
+  char * name;
 {
   return 0;
 }
@@ -443,22 +624,22 @@ static void
 m32r_scomm (ignore)
      int ignore;
 {
-  register char *name;
-  register char c;
-  register char *p;
-  offsetT size;
-  register symbolS *symbolP;
-  offsetT align;
-  int align2;
+  register char *    name;
+  register char      c;
+  register char *    p;
+  offsetT            size;
+  register symbolS * symbolP;
+  offsetT            align;
+  int                align2;
 
   name = input_line_pointer;
   c = get_symbol_end ();
 
   /* just after name is now '\0' */
   p = input_line_pointer;
-  *p = c;
+  * p = c;
   SKIP_WHITESPACE ();
-  if (*input_line_pointer != ',')
+  if (* input_line_pointer != ',')
     {
       as_bad ("Expected comma after symbol-name: rest of line ignored.");
       ignore_rest_of_line ();
@@ -474,11 +655,11 @@ m32r_scomm (ignore)
     }
 
   /* The third argument to .scomm is the alignment.  */
-  if (*input_line_pointer != ',')
+  if (* input_line_pointer != ',')
     align = 8;
   else
     {
-      ++input_line_pointer;
+      ++ input_line_pointer;
       align = get_absolute_expression ();
       if (align <= 0)
        {
@@ -489,7 +670,7 @@ m32r_scomm (ignore)
   /* Convert to a power of 2 alignment.  */
   if (align)
     {
-      for (align2 = 0; (align & 1) == 0; align >>= 1, ++align2)
+      for (align2 = 0; (align & 1) == 0; align >>= 1, ++ align2)
        continue;
       if (align != 1)
        {
@@ -501,9 +682,9 @@ m32r_scomm (ignore)
   else
     align2 = 0;
 
-  *p = 0;
+  * p = 0;
   symbolP = symbol_find_or_make (name);
-  *p = c;
+  * p = c;
 
   if (S_IS_DEFINED (symbolP))
     {
@@ -526,9 +707,9 @@ m32r_scomm (ignore)
 
   if (symbolP->local)
     {
-      segT old_sec = now_seg;
-      int old_subsec = now_subseg;
-      char *pfrag;
+      segT   old_sec    = now_seg;
+      int    old_subsec = now_subseg;
+      char * pfrag;
 
       record_alignment (sbss_section, align2);
       subseg_set (sbss_section, 0);
@@ -539,7 +720,7 @@ m32r_scomm (ignore)
       symbolP->sy_frag = frag_now;
       pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, size,
                        (char *) 0);
-      *pfrag = 0;
+      * pfrag = 0;
       S_SET_SIZE (symbolP, size);
       S_SET_SEGMENT (symbolP, sbss_section);
       S_CLEAR_EXTERNAL (symbolP);
@@ -588,8 +769,8 @@ const relax_typeS md_relax_table[] =
 
 long
 m32r_relax_frag (fragP, stretch)
-     fragS *fragP;
-     long stretch;
+     fragS * fragP;
+     long    stretch;
 {
   /* Address of branch insn.  */
   long address = fragP->fr_address + fragP->fr_fix - 2;
@@ -640,11 +821,11 @@ m32r_relax_frag (fragP, stretch)
 
 int
 md_estimate_size_before_relax (fragP, segment)
-     fragS *fragP;
-     segT segment;
+     fragS * fragP;
+     segT    segment;
 {
-  int old_fr_fix = fragP->fr_fix;
-  char *opcode = fragP->fr_opcode;
+  int    old_fr_fix = fragP->fr_fix;
+  char * opcode = fragP->fr_opcode;
 
   /* The only thing we have to handle here are symbols outside of the
      current segment.  They may be undefined or in a different segment in
@@ -678,8 +859,8 @@ md_estimate_size_before_relax (fragP, segment)
       frag_wane (fragP);
 #else
       {
-       const CGEN_INSN *insn;
-       int i;
+       const CGEN_INSN * insn;
+       int               i;
 
        /* Update the recorded insn.
           Fortunately we don't have to look very far.
@@ -717,8 +898,12 @@ md_convert_frag (abfd, sec, fragP)
   segT sec;
   fragS *fragP;
 {
-  char *opcode, *displacement;
-  int target_address, opcode_address, extension, addend;
+  char * opcode;
+  char * displacement;
+  int    target_address;
+  int    opcode_address;
+  int    extension;
+  int    addend;
 
   opcode = fragP->fr_opcode;
 
@@ -729,19 +914,19 @@ md_convert_frag (abfd, sec, fragP)
     {
     case 1 :
       extension = 0;
-      displacement = &opcode[1];
+      displacement = & opcode[1];
       break;
     case 2 :
       opcode[0] |= 0x80;
       extension = 2;
-      displacement = &opcode[1];
+      displacement = & opcode[1];
       break;
     case 3 :
       opcode[2] = opcode[0] | 0x80;
       md_number_to_chars (opcode, PAR_NOP_INSN, 2);
       opcode_address += 2;
       extension = 4;
-      displacement = &opcode[3];
+      displacement = & opcode[3];
       break;
     default :
       abort ();
@@ -799,8 +984,8 @@ md_convert_frag (abfd, sec, fragP)
 
 long
 md_pcrel_from_section (fixP, sec)
-     fixS *fixP;
-     segT sec;
+     fixS * fixP;
+     segT   sec;
 {
   if (fixP->fx_addsy != (symbolS *) NULL
       && (! S_IS_DEFINED (fixP->fx_addsy)
@@ -820,9 +1005,9 @@ md_pcrel_from_section (fixP, sec)
 
 bfd_reloc_code_real_type
 CGEN_SYM (lookup_reloc) (insn, operand, fixP)
-     const CGEN_INSN *insn;
-     const CGEN_OPERAND *operand;
-     fixS *fixP;
+     const CGEN_INSN *    insn;
+     const CGEN_OPERAND * operand;
+     fixS *               fixP;
 {
   switch (CGEN_OPERAND_TYPE (operand))
     {
@@ -846,16 +1031,16 @@ CGEN_SYM (lookup_reloc) (insn, operand, fixP)
 
 fixS *
 m32r_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;
+     fragS *              frag;
+     int                  where;
+     const CGEN_INSN *    insn;
+     int                  length;
+     const CGEN_OPERAND * operand;
+     int                  opinfo;
+     expressionS *        exp;
 {
-  fixS *fixP = cgen_record_fixup_exp (frag, where, insn, length,
-                                     operand, opinfo, exp);
+  fixS * fixP = cgen_record_fixup_exp (frag, where, insn, length,
+                                     operand, opinfo, exp);
 
   switch (CGEN_OPERAND_TYPE (operand))
     {
@@ -874,11 +1059,11 @@ m32r_cgen_record_fixup_exp (frag, where, insn, length, operand, opinfo, exp)
 
 static void
 m32r_record_hi16 (reloc_type, fixP, seg)
-     int reloc_type;
-     fixS *fixP;
-     segT seg;
+     int    reloc_type;
+     fixS * fixP;
+     segT   seg;
 {
-  struct m32r_hi_fixup *hi_fixup;
+  struct m32r_hi_fixup * hi_fixup;
 
   assert (reloc_type == BFD_RELOC_M32R_HI16_SLO
          || reloc_type == BFD_RELOC_M32R_HI16_ULO);
@@ -886,8 +1071,9 @@ m32r_record_hi16 (reloc_type, fixP, seg)
   hi_fixup = ((struct m32r_hi_fixup *)
              xmalloc (sizeof (struct m32r_hi_fixup)));
   hi_fixup->fixp = fixP;
-  hi_fixup->seg = now_seg;
+  hi_fixup->seg  = now_seg;
   hi_fixup->next = m32r_hi_fixup_list;
+  
   m32r_hi_fixup_list = hi_fixup;
 }
 
@@ -903,12 +1089,12 @@ m32r_record_hi16 (reloc_type, fixP, seg)
 void
 m32r_frob_file ()
 {
-  struct m32r_hi_fixup *l;
+  struct m32r_hi_fixup * l;
 
   for (l = m32r_hi_fixup_list; l != NULL; l = l->next)
     {
-      segment_info_type *seginfo;
-      int pass;
+      segment_info_type * seginfo;
+      int                 pass;
 
       assert (FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_M32R_HI16_SLO
              || FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_M32R_HI16_ULO);
@@ -928,7 +1114,8 @@ m32r_frob_file ()
       seginfo = seg_info (l->seg);
       for (pass = 0; pass < 2; pass++)
        {
-         fixS *f, *prev;
+         fixS * f;
+         fixS * prev;
 
          prev = NULL;
          for (f = seginfo->fix_root; f != NULL; f = f->fx_next)
@@ -944,15 +1131,15 @@ m32r_frob_file ()
                      || prev->fx_addsy != f->fx_addsy
                      || prev->fx_offset !=  f->fx_offset))
                {
-                 fixS **pf;
+                 fixS ** pf;
 
                  /* Move l->fixp before f.  */
                  for (pf = &seginfo->fix_root;
-                      *pf != l->fixp;
-                      pf = &(*pf)->fx_next)
-                   assert (*pf != NULL);
+                      * pf != l->fixp;
+                      pf = & (* pf)->fx_next)
+                   assert (* pf != NULL);
 
-                 *pf = l->fixp->fx_next;
+                 * pf = l->fixp->fx_next;
 
                  l->fixp->fx_next = f;
                  if (prev == NULL)
@@ -982,7 +1169,7 @@ m32r_frob_file ()
 
 int
 m32r_force_relocation (fix)
-     fixS *fix;
+     fixS * fix;
 {
   if (! m32r_relax)
     return 0;
@@ -995,9 +1182,9 @@ m32r_force_relocation (fix)
 
 void
 md_number_to_chars (buf, val, n)
-     char *buf;
+     char * buf;
      valueT val;
-     int n;
+     int    n;
 {
   if (target_big_endian)
     number_to_chars_bigendian (buf, val, n);
@@ -1019,11 +1206,12 @@ md_atof (type, litP, sizeP)
      char *litP;
      int *sizeP;
 {
-  int i,prec;
-  LITTLENUM_TYPE words[MAX_LITTLENUMS];
-  LITTLENUM_TYPE *wordP;
-  char *t;
-  char *atof_ieee ();
+  int              i;
+  int              prec;
+  LITTLENUM_TYPE   words [MAX_LITTLENUMS];
+  LITTLENUM_TYPE * wordP;
+  char *           t;
+  char *           atof_ieee ();
 
   switch (type)
     {
@@ -1044,20 +1232,21 @@ md_atof (type, litP, sizeP)
    /* FIXME: Some targets allow other format chars for bigger sizes here.  */
 
     default:
-      *sizeP = 0;
+      * sizeP = 0;
       return "Bad call to md_atof()";
     }
 
   t = atof_ieee (input_line_pointer, type, words);
   if (t)
     input_line_pointer = t;
-  *sizeP = prec * sizeof (LITTLENUM_TYPE);
+  * sizeP = prec * sizeof (LITTLENUM_TYPE);
 
   if (target_big_endian)
     {
       for (i = 0; i < prec; i++)
        {
-         md_number_to_chars (litP, (valueT) words[i], sizeof (LITTLENUM_TYPE));
+         md_number_to_chars (litP, (valueT) words[i],
+                             sizeof (LITTLENUM_TYPE));
          litP += sizeof (LITTLENUM_TYPE);
        }
     }
@@ -1065,7 +1254,8 @@ md_atof (type, litP, sizeP)
     {
       for (i = prec - 1; i >= 0; i--)
        {
-         md_number_to_chars (litP, (valueT) words[i], sizeof (LITTLENUM_TYPE));
+         md_number_to_chars (litP, (valueT) words[i],
+                             sizeof (LITTLENUM_TYPE));
          litP += sizeof (LITTLENUM_TYPE);
        }
     }