]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gas:
authorJoseph Myers <joseph@codesourcery.com>
Tue, 27 Apr 2010 23:43:25 +0000 (23:43 +0000)
committerJoseph Myers <joseph@codesourcery.com>
Tue, 27 Apr 2010 23:43:25 +0000 (23:43 +0000)
* config/tc-tic6x.h (tic6x_label_list): New.
(tic6x_segment_info_type): Keep a list of labels and a current
frag instead of a boolean for whether labels seen and a count of
instructions.
(tic6x_frag_info, TC_FRAG_TYPE, TC_FRAG_INIT, tic6x_frag_init,
md_do_align, tic6x_do_align, md_end, tic6x_end): New.
* config/tc-tic6x.c (tic6x_frob_label): Put label on list.
(tic6x_cleanup): Correct comment.
(tic6x_free_label_list): New.
(tic6x_cons_align): Free label list and update for
tic6x_segment_info_type changes.
(tic6x_do_align): New.
(md_assemble): Handle list of labels and saved frag for execute
packet.  Create machine-dependent frag for new execute packet and
adjust labels accordingly.
(tic6x_adjust_section, tic6x_frag_init, tic6x_end): New.
(md_convert_frag, md_estimate_size_before_relax): Update comments.

gas/testsuite:
* gas/tic6x/align-1-be.d, gas/tic6x/align-1.d,
gas/tic6x/align-1.s, gas/tic6x/align-2.d, gas/tic6x/align-2.s:
New.

gas/ChangeLog
gas/config/tc-tic6x.c
gas/config/tc-tic6x.h
gas/testsuite/ChangeLog
gas/testsuite/gas/tic6x/align-1-be.d [new file with mode: 0644]
gas/testsuite/gas/tic6x/align-1.d [new file with mode: 0644]
gas/testsuite/gas/tic6x/align-1.s [new file with mode: 0644]
gas/testsuite/gas/tic6x/align-2.d [new file with mode: 0644]
gas/testsuite/gas/tic6x/align-2.s [new file with mode: 0644]

index 1638bc74e85300865152cdf3c347fc35d80768f3..961b7169470c567474369464ee44ad944e9b09d3 100644 (file)
@@ -1,3 +1,23 @@
+2010-04-27  Joseph Myers  <joseph@codesourcery.com>
+
+       * config/tc-tic6x.h (tic6x_label_list): New.
+       (tic6x_segment_info_type): Keep a list of labels and a current
+       frag instead of a boolean for whether labels seen and a count of
+       instructions.
+       (tic6x_frag_info, TC_FRAG_TYPE, TC_FRAG_INIT, tic6x_frag_init,
+       md_do_align, tic6x_do_align, md_end, tic6x_end): New.
+       * config/tc-tic6x.c (tic6x_frob_label): Put label on list.
+       (tic6x_cleanup): Correct comment.
+       (tic6x_free_label_list): New.
+       (tic6x_cons_align): Free label list and update for
+       tic6x_segment_info_type changes.
+       (tic6x_do_align): New.
+       (md_assemble): Handle list of labels and saved frag for execute
+       packet.  Create machine-dependent frag for new execute packet and
+       adjust labels accordingly.
+       (tic6x_adjust_section, tic6x_frag_init, tic6x_end): New.
+       (md_convert_frag, md_estimate_size_before_relax): Update comments.
+
 2010-04-24  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR gas/11535
index d746f9416e997a4ffaebec4e0e8bdbec1e30cb40..5e63c8bd2b6572df2ab48658a29673177f76f241 100644 (file)
@@ -465,8 +465,11 @@ tic6x_unrecognized_line (int c)
 /* Do any target-specific handling of a label required.  */
 
 void
-tic6x_frob_label (symbolS *sym ATTRIBUTE_UNUSED)
+tic6x_frob_label (symbolS *sym)
 {
+  segment_info_type *si;
+  tic6x_label_list *list;
+
   if (tic6x_line_parallel)
     {
       as_bad (_("label after '||'"));
@@ -480,7 +483,11 @@ tic6x_frob_label (symbolS *sym ATTRIBUTE_UNUSED)
       tic6x_line_z = 0;
     }
 
-  seg_info (now_seg)->tc_segment_info_data.seen_label = TRUE;
+  si = seg_info (now_seg);
+  list = si->tc_segment_info_data.label_list;
+  si->tc_segment_info_data.label_list = xmalloc (sizeof (tic6x_label_list));
+  si->tc_segment_info_data.label_list->next = list;
+  si->tc_segment_info_data.label_list->label = sym;
 
   /* Defining tc_frob_label overrides the ELF definition of
      obj_frob_label, so we need to apply its effects here.  */
@@ -515,8 +522,9 @@ tic6x_start_line_hook (void)
   tic6x_end_of_line ();
 }
 
-/* Do target-specific handling immediately after all input files have
-   been read.  */
+/* Do target-specific handling immediately after an input file from
+   the command line, and any other inputs it includes, have been
+   read.  */
 
 void
 tic6x_cleanup (void)
@@ -533,6 +541,20 @@ tic6x_init_after_args (void)
   elf32_tic6x_set_use_rela_p (stdoutput, tic6x_generate_rela);
 }
 
+/* Free LIST of labels (possibly NULL).  */
+
+static void
+tic6x_free_label_list (tic6x_label_list *list)
+{
+  while (list)
+    {
+      tic6x_label_list *old = list;
+
+      list = list->next;
+      free (old);
+    }
+}
+
 /* Handle a data alignment of N bytes.  */
 
 void
@@ -542,12 +564,63 @@ tic6x_cons_align (int n ATTRIBUTE_UNUSED)
 
   /* Data means there is no current execute packet, and that any label
      applies to that data rather than a subsequent instruction.  */
-  seginfo->tc_segment_info_data.num_execute_packet_insns = 0;
-  seginfo->tc_segment_info_data.seen_label = FALSE;
+  tic6x_free_label_list (seginfo->tc_segment_info_data.label_list);
+  seginfo->tc_segment_info_data.label_list = NULL;
+  seginfo->tc_segment_info_data.execute_packet_frag = NULL;
   seginfo->tc_segment_info_data.last_insn_lsb = NULL;
   seginfo->tc_segment_info_data.spmask_addr = NULL;
 }
 
+/* Handle an alignment directive.  Return TRUE if the
+   machine-independent frag generation should be skipped.  */
+
+bfd_boolean
+tic6x_do_align (int n, char *fill, int len ATTRIBUTE_UNUSED, int max)
+{
+  /* Given code alignments of 4, 8, 16 or 32 bytes, we try to handle
+     them in the md_end pass by inserting NOPs in parallel with
+     previous instructions.  We only do this in sections containing
+     nothing but instructions.  Code alignments of 1 or 2 bytes have
+     no effect in such sections (but we record them with
+     machine-dependent frags anyway so they can be skipped or
+     converted to machine-independent), while those of more than 64
+     bytes cannot reliably be handled in this way.  */
+  if (n > 0
+      && max >= 0
+      && max < (1 << n)
+      && !need_pass_2
+      && fill == NULL
+      && subseg_text_p (now_seg))
+    {
+      fragS *align_frag;
+      char *p;
+
+      if (n > 5)
+       return FALSE;
+
+      /* Machine-independent code would generate a frag here, but we
+        wish to handle it in a machine-dependent way.  */
+      if (frag_now_fix () != 0)
+       {
+         if (frag_now->fr_type != rs_machine_dependent)
+           frag_wane (frag_now);
+
+         frag_new (0);
+       }
+      frag_grow (32);
+      align_frag = frag_now;
+      p = frag_var (rs_machine_dependent, 32, 32, max, NULL, n, NULL);
+      /* This must be the same as the frag to which a pointer was just
+        saved.  */
+      if (p != align_frag->fr_literal)
+       abort ();
+      align_frag->tc_frag_data.is_insns = FALSE;
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
 /* Types of operand for parsing purposes.  These are used as bit-masks
    to tell tic6x_parse_operand what forms of operand are
    permitted.  */
@@ -2474,7 +2547,7 @@ md_assemble (char *str)
   bfd_boolean this_line_spmask;
   unsigned int this_line_creg;
   unsigned int this_line_z;
-  bfd_boolean this_insn_label;
+  tic6x_label_list *this_insn_label_list;
   segment_info_type *seginfo;
   tic6x_opcode_list *opc_list, *opc;
   tic6x_func_unit_base func_unit_base = tic6x_func_unit_nfu;
@@ -2502,6 +2575,7 @@ md_assemble (char *str)
   int fix_pcrel = 0;
   bfd_reloc_code_real_type fx_r_type = BFD_RELOC_UNUSED;
   bfd_boolean fix_adda = FALSE;
+  fragS *insn_frag;
   char *output;
 
   p = str;
@@ -2524,8 +2598,8 @@ md_assemble (char *str)
   tic6x_line_creg = 0;
   tic6x_line_z = 0;
   seginfo = seg_info (now_seg);
-  this_insn_label = seginfo->tc_segment_info_data.seen_label;
-  seginfo->tc_segment_info_data.seen_label = FALSE;
+  this_insn_label_list = seginfo->tc_segment_info_data.label_list;
+  seginfo->tc_segment_info_data.label_list = NULL;
 
   opc_list = hash_find_n (opcode_hash, str, p - str);
   if (opc_list == NULL)
@@ -2979,19 +3053,20 @@ md_assemble (char *str)
 
   if (this_line_parallel)
     {
-      if (seginfo->tc_segment_info_data.num_execute_packet_insns == 0)
+      insn_frag = seginfo->tc_segment_info_data.execute_packet_frag;
+      if (insn_frag == NULL)
        {
          as_bad (_("parallel instruction not following another instruction"));
          return;
        }
 
-      if (seginfo->tc_segment_info_data.num_execute_packet_insns >= 8)
+      if (insn_frag->fr_fix >= 32)
        {
          as_bad (_("too many instructions in execute packet"));
          return;
        }
 
-      if (this_insn_label)
+      if (this_insn_label_list != NULL)
        as_bad (_("label not at start of execute packet"));
 
       if (opct->flags & TIC6X_FLAG_FIRST)
@@ -2999,11 +3074,40 @@ md_assemble (char *str)
                opc_len, str);
 
       *seginfo->tc_segment_info_data.last_insn_lsb |= 0x1;
+      output = insn_frag->fr_literal + insn_frag->fr_fix;
     }
   else
     {
-      seginfo->tc_segment_info_data.num_execute_packet_insns = 0;
+      tic6x_label_list *l;
+
       seginfo->tc_segment_info_data.spmask_addr = NULL;
+
+      /* Start a new frag for this execute packet.  */
+      if (frag_now_fix () != 0)
+       {
+         if (frag_now->fr_type != rs_machine_dependent)
+           frag_wane (frag_now);
+
+         frag_new (0);
+       }
+      frag_grow (32);
+      insn_frag = seginfo->tc_segment_info_data.execute_packet_frag = frag_now;
+      for (l = this_insn_label_list; l; l = l->next)
+       {
+         symbol_set_frag (l->label, frag_now);
+         S_SET_VALUE (l->label, 0);
+         S_SET_SEGMENT (l->label, now_seg);
+       }
+      tic6x_free_label_list (this_insn_label_list);
+      dwarf2_emit_insn (0);
+      output = frag_var (rs_machine_dependent, 32, 32, 0, NULL, 0, NULL);
+      /* This must be the same as the frag to which a pointer was just
+        saved.  */
+      if (output != insn_frag->fr_literal)
+       abort ();
+      insn_frag->tc_frag_data.is_insns = TRUE;
+      insn_frag->tc_frag_data.can_cross_fp_boundary
+       = tic6x_can_cross_fp_boundary;
     }
 
   if (opct->flags & TIC6X_FLAG_SPLOOP)
@@ -3050,17 +3154,16 @@ md_assemble (char *str)
     }
 
   record_alignment (now_seg, 5);
-  output = frag_more (4);
   md_number_to_chars (output, opcode_value, 4);
   if (fix_needed)
-    tic6x_fix_new_exp (frag_now, output - frag_now->fr_literal, 4, fix_exp,
+    tic6x_fix_new_exp (insn_frag, output - insn_frag->fr_literal, 4, fix_exp,
                       fix_pcrel, fx_r_type, fix_adda);
-  seginfo->tc_segment_info_data.num_execute_packet_insns++;
+  insn_frag->fr_fix += 4;
+  insn_frag->fr_var -= 4;
   seginfo->tc_segment_info_data.last_insn_lsb
     = (target_big_endian ? output + 3 : output);
   if (opct->flags & TIC6X_FLAG_SPMASK)
     seginfo->tc_segment_info_data.spmask_addr = output;
-  dwarf2_emit_insn (4);
 }
 
 /* Modify NEWVAL (32-bit) by inserting VALUE, shifted right by SHIFT
@@ -3363,7 +3466,319 @@ md_atof (int type, char *litP, int *sizeP)
   return ieee_md_atof (type, litP, sizeP, target_big_endian);
 }
 
-/* No machine-dependent frags yet.  */
+/* Adjust the frags in SECTION (see tic6x_end).  */
+
+static void
+tic6x_adjust_section (bfd *abfd ATTRIBUTE_UNUSED, segT section,
+                     void *dummy ATTRIBUTE_UNUSED)
+{
+  segment_info_type *info;
+  frchainS *frchp;
+  fragS *fragp;
+  bfd_boolean have_code = FALSE;
+  bfd_boolean have_non_code = FALSE;
+
+  info = seg_info (section);
+  if (info == NULL)
+    return;
+
+  for (frchp = info->frchainP; frchp; frchp = frchp->frch_next)
+    for (fragp = frchp->frch_root; fragp; fragp = fragp->fr_next)
+      switch (fragp->fr_type)
+       {
+       case rs_machine_dependent:
+         if (fragp->tc_frag_data.is_insns)
+           have_code = TRUE;
+         break;
+
+       case rs_dummy:
+       case rs_fill:
+         if (fragp->fr_fix > 0)
+           have_non_code = TRUE;
+         break;
+
+       default:
+         have_non_code = TRUE;
+         break;
+       }
+
+  /* Process alignment requirements in a code-only section.  */
+  if (have_code && !have_non_code)
+    {
+      /* If we need to insert an odd number of instructions to meet an
+        alignment requirement, there must have been an odd number of
+        instructions since the last 8-byte-aligned execute packet
+        boundary.  So there must have been an execute packet with an
+        odd number (and so a number fewer than 8) of instructions
+        into which we can insert a NOP without breaking any previous
+        alignments.
+
+        If then we need to insert a number 2 mod 4 of instructions,
+        the number of instructions since the last 16-byte-aligned
+        execute packet boundary must be 2 mod 4.  So between that
+        boundary and the following 8-byte-aligned boundary there must
+        either be at least one execute packet with 2-mod-4
+        instructions, or at least two with an odd number of
+        instructions; again, greedily inserting NOPs as soon as
+        possible suffices to meet the alignment requirement.
+
+        If then we need to insert 4 instructions, we look between the
+        last 32-byte-aligned boundary and the following
+        16-byte-aligned boundary.  The sizes of the execute packets
+        in this range total 4 instructions mod 8, so again there is
+        room for greedy insertion of NOPs to meet the alignment
+        requirement, and before any intermediate point with 8-byte
+        (2-instruction) alignment requirement the sizes of execute
+        packets (and so the room for NOPs) will total 2 instructions
+        mod 4 so greedy insertion will not break such alignments.
+
+        So we can always meet these alignment requirements by
+        inserting NOPs in parallel with existing execute packets, and
+        by induction the approach described above inserts the minimum
+        number of such NOPs.  */
+
+      /* The number of NOPs we are currently looking to insert, if we
+        have gone back to insert NOPs.  */
+      unsigned int want_insert = 0;
+
+      /* Out of that number, the number inserted so far in the current
+        stage of the above algorithm.  */
+      unsigned int want_insert_done_so_far = 0;
+
+      /* The position mod 32 at the start of the current frag.  */
+      unsigned int pos = 0;
+
+      /* The locations in the frag chain of the most recent frags at
+        the start of which there is the given alignment.  */
+      frchainS *frchp_last32, *frchp_last16, *frchp_last8;
+      fragS *fragp_last32, *fragp_last16, *fragp_last8;
+      unsigned int pos_last32, pos_last16, pos_last8;
+
+      frchp_last32 = frchp_last16 = frchp_last8 = info->frchainP;
+      fragp_last32 = fragp_last16 = fragp_last8 = info->frchainP->frch_root;
+      pos_last32 = pos_last16 = pos_last8 = 0;
+
+      for (frchp = info->frchainP; frchp; frchp = frchp->frch_next)
+       for (fragp = frchp->frch_root; fragp; fragp = fragp->fr_next)
+       look_at_frag:
+         {
+           bfd_boolean go_back = FALSE;
+           frchainS *frchp_next;
+           fragS *fragp_next;
+
+           if (fragp->fr_type != rs_machine_dependent)
+             continue;
+
+           if (fragp->tc_frag_data.is_insns
+               && pos + fragp->fr_fix > 32
+               && !fragp->tc_frag_data.can_cross_fp_boundary)
+             {
+               /* As described above, we should always have met an
+                  alignment requirement by the time we come back to
+                  it.  */
+               if (want_insert)
+                 abort ();
+
+               if (pos & 3)
+                 abort ();
+               want_insert = (32 - pos) >> 2;
+               if (want_insert > 7)
+                 abort ();
+               want_insert_done_so_far = 0;
+               go_back = TRUE;
+             }
+
+           if (!fragp->tc_frag_data.is_insns)
+             {
+               unsigned int would_insert_bytes;
+
+               if (!(pos & ((1 << fragp->fr_offset) - 1)))
+                 /* This alignment requirement is already met.  */
+                 continue;
+
+               /* As described above, we should always have met an
+                  alignment requirement by the time we come back to
+                  it.  */
+               if (want_insert)
+                 abort ();
+
+               /* We may not be able to meet this requirement within
+                  the given number of characters.  */
+               would_insert_bytes
+                 = ((1 << fragp->fr_offset)
+                    - (pos & ((1 << fragp->fr_offset) - 1)));
+
+               if (fragp->fr_subtype != 0
+                   && would_insert_bytes > fragp->fr_subtype)
+                 continue;
+
+               /* An unmet alignment must be 8, 16 or 32 bytes;
+                  smaller ones must always be met within code-only
+                  sections and larger ones cause the section not to
+                  be code-only.  */
+               if (fragp->fr_offset != 3
+                   && fragp->fr_offset != 4
+                   && fragp->fr_offset != 5)
+                 abort ();
+
+               if (would_insert_bytes & 3)
+                 abort ();
+               want_insert = would_insert_bytes >> 2;
+               if (want_insert > 7)
+                 abort ();
+               want_insert_done_so_far = 0;
+               go_back = TRUE;
+             }
+           else if (want_insert && !go_back)
+             {
+               unsigned int num_insns = fragp->fr_fix >> 2;
+               unsigned int max_poss_nops = 8 - num_insns;
+
+               if (max_poss_nops)
+                 {
+                   unsigned int cur_want_nops, max_want_nops, do_nops, i;
+
+                   if (want_insert & 1)
+                     cur_want_nops = 1;
+                   else if (want_insert & 2)
+                     cur_want_nops = 2;
+                   else if (want_insert & 4)
+                     cur_want_nops = 4;
+                   else
+                     abort ();
+
+                   max_want_nops = cur_want_nops - want_insert_done_so_far;
+
+                   do_nops = (max_poss_nops < max_want_nops
+                              ? max_poss_nops
+                              : max_want_nops);
+                   for (i = 0; i < do_nops; i++)
+                     {
+                       md_number_to_chars (fragp->fr_literal + fragp->fr_fix,
+                                           0, 4);
+                       if (target_big_endian)
+                         fragp->fr_literal[fragp->fr_fix - 1] |= 0x1;
+                       else
+                         fragp->fr_literal[fragp->fr_fix - 4] |= 0x1;
+                       fragp->fr_fix += 4;
+                       fragp->fr_var -= 4;
+                     }
+                   want_insert_done_so_far += do_nops;
+                   if (want_insert_done_so_far == cur_want_nops)
+                     {
+                       want_insert -= want_insert_done_so_far;
+                       want_insert_done_so_far = 0;
+                       if (want_insert)
+                         go_back = TRUE;
+                     }
+                 }
+             }
+           if (go_back)
+             {
+               if (want_insert & 1)
+                 {
+                   frchp = frchp_last8;
+                   fragp = fragp_last8;
+                   pos = pos_last8;
+                 }
+               else if (want_insert & 2)
+                 {
+                   frchp = frchp_last8 = frchp_last16;
+                   fragp = fragp_last8 = fragp_last16;
+                   pos = pos_last8 = pos_last16;
+                 }
+               else if (want_insert & 4)
+                 {
+                   frchp = frchp_last8 = frchp_last16 = frchp_last32;
+                   fragp = fragp_last8 = fragp_last16 = fragp_last32;
+                   pos = pos_last8 = pos_last16 = pos_last32;
+                 }
+               else
+                 abort ();
+
+               goto look_at_frag;
+             }
+
+           /* Update current position for moving past a code
+              frag.  */
+           pos += fragp->fr_fix;
+           pos &= 31;
+           frchp_next = frchp;
+           fragp_next = fragp->fr_next;
+           if (fragp_next == NULL)
+             {
+               frchp_next = frchp->frch_next;
+               if (frchp_next != NULL)
+                 fragp_next = frchp_next->frch_root;
+             }
+           if (!(pos & 7))
+             {
+               frchp_last8 = frchp_next;
+               fragp_last8 = fragp_next;
+               pos_last8 = pos;
+             }
+           if (!(pos & 15))
+             {
+               frchp_last16 = frchp_next;
+               fragp_last16 = fragp_next;
+               pos_last16 = pos;
+             }
+           if (!(pos & 31))
+             {
+               frchp_last32 = frchp_next;
+               fragp_last32 = fragp_next;
+               pos_last32 = pos;
+             }
+         }
+    }
+
+  /* Now convert the machine-dependent frags to machine-independent
+     ones.  */
+  for (frchp = info->frchainP; frchp; frchp = frchp->frch_next)
+    for (fragp = frchp->frch_root; fragp; fragp = fragp->fr_next)
+      {
+       if (fragp->fr_type == rs_machine_dependent)
+         {
+           if (fragp->tc_frag_data.is_insns)
+             frag_wane (fragp);
+           else
+             {
+               fragp->fr_type = rs_align_code;
+               fragp->fr_var = 1;
+               *fragp->fr_literal = 0;
+             }
+         }
+      }
+}
+
+/* Initialize the machine-dependent parts of a frag.  */
+
+void
+tic6x_frag_init (fragS *fragp)
+{
+  fragp->tc_frag_data.is_insns = FALSE;
+  fragp->tc_frag_data.can_cross_fp_boundary = FALSE;
+}
+
+/* Do machine-dependent manipulations of the frag chains after all
+   input has been read and before the machine-independent sizing and
+   relaxing.  */
+
+void
+tic6x_end (void)
+{
+  /* Meeting alignment requirements may require inserting NOPs in
+     parallel in execute packets earlier in the segment.  Future
+     16-bit instruction generation involves whole-segment optimization
+     to determine the best choice and ordering of 32-bit or 16-bit
+     instructions.  This doesn't fit will in the general relaxation
+     framework, so handle alignment and 16-bit instruction generation
+     here.  */
+  bfd_map_over_sections (stdoutput, tic6x_adjust_section, NULL);
+}
+
+/* No machine-dependent frags at this stage; all converted in
+   tic6x_end.  */
 
 void
 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec ATTRIBUTE_UNUSED,
@@ -3372,7 +3787,8 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec ATTRIBUTE_UNUSED,
   abort ();
 }
 
-/* No machine-dependent frags yet.  */
+/* No machine-dependent frags at this stage; all converted in
+   tic6x_end.  */
 
 int
 md_estimate_size_before_relax (fragS *fragp ATTRIBUTE_UNUSED,
index 087b9e984529ec153926efba5da83f754facee18..0285db4baf93b07e6822769a0afd09c03de0313a 100644 (file)
                         ? "elf32-tic6x-be"     \
                         : "elf32-tic6x-le")
 
-typedef struct
+typedef struct tic6x_label_list
 {
-  /* Number of instructions in the current execute packet.  */
-  unsigned int num_execute_packet_insns;
+  struct tic6x_label_list *next;
+  symbolS *label;
+} tic6x_label_list;
 
-  /* Whether a label has been seen since the last instruction or data
-     (in which case a following instruction may not have parallel
-     bars, but must start a new execute packet).  */
-  bfd_boolean seen_label;
+typedef struct
+{
+  /* Any labels seen since the last instruction or data.  If not NULL,
+     a following instruction may not have parallel bars, but must
+     start a new execute packet.  */
+  tic6x_label_list *label_list;
 
   /* Whether compact instructions are forbidden here.  */
   bfd_boolean nocmp;
 
+  /* If there is a current execute packet, the frag being used for
+     that execute packet.  */
+  fragS *execute_packet_frag;
+
   /* If there is a current execute packet, a pointer to the
      least-significant byte of the last instruction in it (for setting
      the p-bit).  */
@@ -68,6 +75,20 @@ typedef struct
 } tic6x_segment_info_type;
 #define TC_SEGMENT_INFO_TYPE tic6x_segment_info_type
 
+typedef struct
+{
+  /* Whether this machine-dependent frag is used for instructions (as
+     opposed to code alignment).  */
+  bfd_boolean is_insns;
+
+  /* For a frag used for instructions, whether it is may cross a fetch
+     packet boundary (subject to alignment requirements).  */
+  bfd_boolean can_cross_fp_boundary;
+} tic6x_frag_info;
+#define TC_FRAG_TYPE tic6x_frag_info
+#define TC_FRAG_INIT(fragP) tic6x_frag_init (fragP)
+extern void tic6x_frag_init (fragS *fragp);
+
 typedef struct
 {
   /* Whether this fix was for an ADDA instruction.  If so, a constant
@@ -91,6 +112,16 @@ extern void tic6x_cleanup (void);
 #define md_cons_align(n) tic6x_cons_align (n)
 extern void tic6x_cons_align (int n);
 
+#define md_do_align(n, fill, len, max, label)  \
+  do {                                         \
+    if (tic6x_do_align (n, fill, len, max))    \
+      goto label;                              \
+  } while (0)
+extern bfd_boolean tic6x_do_align (int n, char *fill, int len, int max);
+
+#define md_end() tic6x_end ();
+extern void tic6x_end (void);
+
 #define md_parse_name(name, exprP, mode, nextcharP)    \
   tic6x_parse_name (name, exprP, mode, nextcharP)
 extern int tic6x_parse_name (const char *name, expressionS *exprP,
index 8e3df9ef946d302b3d75f40d21af737573fecb66..f381115a4e87bbf78e743e31877856f8be5e86c7 100644 (file)
@@ -1,3 +1,9 @@
+2010-04-27  Joseph Myers  <joseph@codesourcery.com>
+
+       * gas/tic6x/align-1-be.d, gas/tic6x/align-1.d,
+       gas/tic6x/align-1.s, gas/tic6x/align-2.d, gas/tic6x/align-2.s:
+       New.
+
 2010-04-24  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR gas/11535
diff --git a/gas/testsuite/gas/tic6x/align-1-be.d b/gas/testsuite/gas/tic6x/align-1-be.d
new file mode 100644 (file)
index 0000000..f99a6cf
--- /dev/null
@@ -0,0 +1,82 @@
+#objdump: -dr --prefix-addresses --show-raw-insn
+#name: C6X code alignment 1, big-endian
+#as: -march=c674x -mbig-endian
+#source: align-1.s
+
+.*: *file format elf32-tic6x-be
+
+
+Disassembly of section \.text:
+0+ <[^>]*> 00002000[ \t]+nop 2
+0+4 <[^>]*> 00004000[ \t]+nop 3
+0+8 <[^>]*> 00006000[ \t]+nop 4
+0+c <[^>]*> 00008000[ \t]+nop 5
+0+10 <[^>]*> 00008001[ \t]+nop 5
+0+14 <[^>]*> 00000000[ \t]+\|\| nop 1
+0+18 <[^>]*> 0000a001[ \t]+nop 6
+0+1c <[^>]*> 00000000[ \t]+\|\| nop 1
+0+20 <[^>]*> 0000c001[ \t]+nop 7
+0+24 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+28 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+2c <[^>]*> 00000001[ \t]+\|\| nop 1
+0+30 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+34 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+38 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+3c <[^>]*> 00000000[ \t]+\|\| nop 1
+0+40 <[^>]*> 00006001[ \t]+nop 4
+0+44 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+48 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+4c <[^>]*> 00000001[ \t]+\|\| nop 1
+0+50 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+54 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+58 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+5c <[^>]*> 00000000[ \t]+\|\| nop 1
+0+60 <[^>]*> 00002001[ \t]+nop 2
+0+64 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+68 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+6c <[^>]*> 00000001[ \t]+\|\| nop 1
+0+70 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+74 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+78 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+7c <[^>]*> 00000000[ \t]+\|\| nop 1
+0+80 <[^>]*> 00002001[ \t]+nop 2
+0+84 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+88 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+8c <[^>]*> 00000001[ \t]+\|\| nop 1
+0+90 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+94 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+98 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+9c <[^>]*> 00000000[ \t]+\|\| nop 1
+0+a0 <[^>]*> 00000001[ \t]+nop 1
+0+a4 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+a8 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+ac <[^>]*> 00000000[ \t]+\|\| nop 1
+0+b0 <[^>]*> 00002001[ \t]+nop 2
+0+b4 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+b8 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+bc <[^>]*> 00000000[ \t]+\|\| nop 1
+0+c0 <[^>]*> 00006001[ \t]+nop 4
+0+c4 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+c8 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+cc <[^>]*> 00000001[ \t]+\|\| nop 1
+0+d0 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+d4 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+d8 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+dc <[^>]*> 00000000[ \t]+\|\| nop 1
+0+e0 <[^>]*> 00008001[ \t]+nop 5
+0+e4 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+e8 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+ec <[^>]*> 00000001[ \t]+\|\| nop 1
+0+f0 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+f4 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+f8 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+fc <[^>]*> 00000000[ \t]+\|\| nop 1
+0+100 <[^>]*> 00006001[ \t]+nop 4
+0+104 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+108 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+10c <[^>]*> 00000001[ \t]+\|\| nop 1
+0+110 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+114 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+118 <[^>]*> 00000001[ \t]+\|\| nop 1
+[ \t]*\.\.\.
+0+13c <[^>]*> 00004000[ \t]+nop 3
diff --git a/gas/testsuite/gas/tic6x/align-1.d b/gas/testsuite/gas/tic6x/align-1.d
new file mode 100644 (file)
index 0000000..ea9c3fd
--- /dev/null
@@ -0,0 +1,81 @@
+#objdump: -dr --prefix-addresses --show-raw-insn
+#name: C6X code alignment 1
+#as: -march=c674x -mlittle-endian
+
+.*: *file format elf32-tic6x-le
+
+
+Disassembly of section \.text:
+0+ <[^>]*> 00002000[ \t]+nop 2
+0+4 <[^>]*> 00004000[ \t]+nop 3
+0+8 <[^>]*> 00006000[ \t]+nop 4
+0+c <[^>]*> 00008000[ \t]+nop 5
+0+10 <[^>]*> 00008001[ \t]+nop 5
+0+14 <[^>]*> 00000000[ \t]+\|\| nop 1
+0+18 <[^>]*> 0000a001[ \t]+nop 6
+0+1c <[^>]*> 00000000[ \t]+\|\| nop 1
+0+20 <[^>]*> 0000c001[ \t]+nop 7
+0+24 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+28 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+2c <[^>]*> 00000001[ \t]+\|\| nop 1
+0+30 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+34 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+38 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+3c <[^>]*> 00000000[ \t]+\|\| nop 1
+0+40 <[^>]*> 00006001[ \t]+nop 4
+0+44 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+48 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+4c <[^>]*> 00000001[ \t]+\|\| nop 1
+0+50 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+54 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+58 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+5c <[^>]*> 00000000[ \t]+\|\| nop 1
+0+60 <[^>]*> 00002001[ \t]+nop 2
+0+64 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+68 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+6c <[^>]*> 00000001[ \t]+\|\| nop 1
+0+70 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+74 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+78 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+7c <[^>]*> 00000000[ \t]+\|\| nop 1
+0+80 <[^>]*> 00002001[ \t]+nop 2
+0+84 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+88 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+8c <[^>]*> 00000001[ \t]+\|\| nop 1
+0+90 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+94 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+98 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+9c <[^>]*> 00000000[ \t]+\|\| nop 1
+0+a0 <[^>]*> 00000001[ \t]+nop 1
+0+a4 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+a8 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+ac <[^>]*> 00000000[ \t]+\|\| nop 1
+0+b0 <[^>]*> 00002001[ \t]+nop 2
+0+b4 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+b8 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+bc <[^>]*> 00000000[ \t]+\|\| nop 1
+0+c0 <[^>]*> 00006001[ \t]+nop 4
+0+c4 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+c8 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+cc <[^>]*> 00000001[ \t]+\|\| nop 1
+0+d0 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+d4 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+d8 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+dc <[^>]*> 00000000[ \t]+\|\| nop 1
+0+e0 <[^>]*> 00008001[ \t]+nop 5
+0+e4 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+e8 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+ec <[^>]*> 00000001[ \t]+\|\| nop 1
+0+f0 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+f4 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+f8 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+fc <[^>]*> 00000000[ \t]+\|\| nop 1
+0+100 <[^>]*> 00006001[ \t]+nop 4
+0+104 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+108 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+10c <[^>]*> 00000001[ \t]+\|\| nop 1
+0+110 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+114 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+118 <[^>]*> 00000001[ \t]+\|\| nop 1
+[ \t]*\.\.\.
+0+13c <[^>]*> 00004000[ \t]+nop 3
diff --git a/gas/testsuite/gas/tic6x/align-1.s b/gas/testsuite/gas/tic6x/align-1.s
new file mode 100644 (file)
index 0000000..b7ccfec
--- /dev/null
@@ -0,0 +1,82 @@
+# Test handling of code alignment.
+.text
+.nocmp
+.globl f
+f:
+# Fetch packet.
+       nop 2
+.align 0
+       nop 3
+.align 1
+       nop 4
+.align 2
+       nop 5
+       nop 5
+.align 3
+       nop 6
+.align 4
+# Fetch packet.
+       nop 7
+.align 5
+# Fetch packet.
+       nop 4
+# Fetch packet.
+       nop 2
+||     nop
+||     nop
+||     nop
+||     nop
+||     nop
+||     nop
+||     nop
+# Fetch packet.
+       nop 2
+||     nop
+||     nop
+||     nop
+||     nop
+||     nop
+||     nop
+||     nop
+.align 5
+# Fetch packet.
+       nop
+||     nop
+.align 3
+       nop 2
+||     nop
+||     nop
+||     nop
+.align 4
+# Fetch packet.
+       nop 4
+||     nop
+||     nop
+||     nop
+||     nop
+||     nop
+||     nop
+# Fetch packet.
+       nop 5
+||     nop
+||     nop
+||     nop
+||     nop
+||     nop
+# Fetch packet.
+       nop 4
+||     nop
+||     nop
+||     nop
+||     nop
+||     nop
+||     nop
+.align 5
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop 3
diff --git a/gas/testsuite/gas/tic6x/align-2.d b/gas/testsuite/gas/tic6x/align-2.d
new file mode 100644 (file)
index 0000000..85e0b6b
--- /dev/null
@@ -0,0 +1,104 @@
+#objdump: -dr --prefix-addresses --show-raw-insn
+#name: C6X code alignment 2
+#as: -mlittle-endian
+
+.*: *file format elf32-tic6x-le
+
+
+Disassembly of section \.text:
+0+ <[^>]*> 00002001[ \t]+nop 2
+0+4 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+8 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+c <[^>]*> 00000001[ \t]+\|\| nop 1
+0+10 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+14 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+18 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+1c <[^>]*> 00000000[ \t]+\|\| nop 1
+0+20 <[^>]*> 00004001[ \t]+nop 3
+0+24 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+28 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+2c <[^>]*> 00000001[ \t]+\|\| nop 1
+0+30 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+34 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+38 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+3c <[^>]*> 00000000[ \t]+\|\| nop 1
+0+40 <[^>]*> 00006001[ \t]+nop 4
+0+44 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+48 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+4c <[^>]*> 00000000[ \t]+\|\| nop 1
+0+50 <[^>]*> 00008001[ \t]+nop 5
+0+54 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+58 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+5c <[^>]*> 00000001[ \t]+\|\| nop 1
+0+60 <[^>]*> 00000000[ \t]+\|\| nop 1
+0+64 <[^>]*> 0000a001[ \t]+nop 6
+0+68 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+6c <[^>]*> 00000001[ \t]+\|\| nop 1
+0+70 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+74 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+78 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+7c <[^>]*> 00000000[ \t]+\|\| nop 1
+0+80 <[^>]*> 00006001[ \t]+nop 4
+0+84 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+88 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+8c <[^>]*> 00000000[ \t]+\|\| nop 1
+0+90 <[^>]*> 00008001[ \t]+nop 5
+0+94 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+98 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+9c <[^>]*> 00000001[ \t]+\|\| nop 1
+0+a0 <[^>]*> 00000000[ \t]+\|\| nop 1
+0+a4 <[^>]*> 0000a001[ \t]+nop 6
+0+a8 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+ac <[^>]*> 00000001[ \t]+\|\| nop 1
+0+b0 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+b4 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+b8 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+bc <[^>]*> 00000000[ \t]+\|\| nop 1
+0+c0 <[^>]*> 00006001[ \t]+nop 4
+0+c4 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+c8 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+cc <[^>]*> 00000000[ \t]+\|\| nop 1
+0+d0 <[^>]*> 00008001[ \t]+nop 5
+0+d4 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+d8 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+dc <[^>]*> 00000001[ \t]+\|\| nop 1
+0+e0 <[^>]*> 00000000[ \t]+\|\| nop 1
+0+e4 <[^>]*> 0000a001[ \t]+nop 6
+0+e8 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+ec <[^>]*> 00000001[ \t]+\|\| nop 1
+0+f0 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+f4 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+f8 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+fc <[^>]*> 00000000[ \t]+\|\| nop 1
+0+100 <[^>]*> 00006001[ \t]+nop 4
+0+104 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+108 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+10c <[^>]*> 00000000[ \t]+\|\| nop 1
+0+110 <[^>]*> 00008001[ \t]+nop 5
+0+114 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+118 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+11c <[^>]*> 00000001[ \t]+\|\| nop 1
+0+120 <[^>]*> 00000000[ \t]+\|\| nop 1
+0+124 <[^>]*> 0000a001[ \t]+nop 6
+0+128 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+12c <[^>]*> 00000001[ \t]+\|\| nop 1
+0+130 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+134 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+138 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+13c <[^>]*> 00000000[ \t]+\|\| nop 1
+0+140 <[^>]*> 00002001[ \t]+nop 2
+0+144 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+148 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+14c <[^>]*> 00000001[ \t]+\|\| nop 1
+0+150 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+154 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+158 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+15c <[^>]*> 00000000[ \t]+\|\| nop 1
+0+160 <[^>]*> 00004001[ \t]+nop 3
+0+164 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+168 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+16c <[^>]*> 00000001[ \t]+\|\| nop 1
+0+170 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+174 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+178 <[^>]*> 00000001[ \t]+\|\| nop 1
+0+17c <[^>]*> 00000000[ \t]+\|\| nop 1
diff --git a/gas/testsuite/gas/tic6x/align-2.s b/gas/testsuite/gas/tic6x/align-2.s
new file mode 100644 (file)
index 0000000..4f00197
--- /dev/null
@@ -0,0 +1,112 @@
+# Test handling of code alignment: architecture-dependent whether
+# execute packets can cross fetch packet boundaries.
+.text
+.nocmp
+.globl f
+f:
+.arch c62x
+# Fetch packet.
+       nop 2
+||     nop
+||     nop
+||     nop
+# Fetch packet.
+       nop 3
+||     nop
+||     nop
+||     nop
+||     nop
+||     nop
+||     nop
+||     nop
+.arch c64x
+# Fetch packet.
+       nop 4
+||     nop
+||     nop
+||     nop
+       nop 5
+||     nop
+||     nop
+||     nop
+# Fetch packet.
+||     nop
+       nop 6
+||     nop
+||     nop
+||     nop
+||     nop
+||     nop
+||     nop
+.arch c64x+
+# Fetch packet.
+       nop 4
+||     nop
+||     nop
+||     nop
+       nop 5
+||     nop
+||     nop
+||     nop
+# Fetch packet.
+||     nop
+       nop 6
+||     nop
+||     nop
+||     nop
+||     nop
+||     nop
+||     nop
+.arch c674x
+# Fetch packet.
+       nop 4
+||     nop
+||     nop
+||     nop
+       nop 5
+||     nop
+||     nop
+||     nop
+# Fetch packet.
+||     nop
+       nop 6
+||     nop
+||     nop
+||     nop
+||     nop
+||     nop
+||     nop
+.arch c67x+
+# Fetch packet.
+       nop 4
+||     nop
+||     nop
+||     nop
+       nop 5
+||     nop
+||     nop
+||     nop
+# Fetch packet.
+||     nop
+       nop 6
+||     nop
+||     nop
+||     nop
+||     nop
+||     nop
+||     nop
+.arch c67x
+# Fetch packet.
+       nop 2
+||     nop
+||     nop
+||     nop
+# Fetch packet.
+       nop 3
+||     nop
+||     nop
+||     nop
+||     nop
+||     nop
+||     nop
+||     nop