Patch: Add a stop bit in alignment for alloc.
H. J. Lu
hjl@lucon.org
Wed Mar 3 03:01:00 GMT 2004
On Tue, Mar 02, 2004 at 06:24:44PM -0800, Jim Wilson wrote:
> On Tue, 2004-03-02 at 12:36, H. J. Lu wrote:
> > * config/tc-ia64.c (align_frag): New.
> > (md_assemble): Set the tc_frag_data field in align_frag for
> > IA64_OPCODE_FIRST instructions.
> > (ia64_md_do_align): Set align_frag.
> > (ia64_handle_align): Add a stop bit if needed.
>
> This looks good to me.
>
> However, I don't think it is fool proof. When we create an
> rs_align_code frag, we call frag_align_code, which calls frag_var, which
> calls frag_grow with the requested alignment - 1. If there is no room
> left in this obstack, then frag_grow will create a new frag. So in some
> cases, the alignment frag will be the one after align_frag.
>
> There is also a loop in frag_grow which implies that the alignment frag
> could be arbitrarily later, however, it isn't clear to me why the loop
> is there. So it looks like in rare cases the alignment frag could be
> two after align_frag, and maybe in even rarer cases it could be farther.
>
> In order to handle this, I think we need a loop to search forward from
> align_frag to find the real alignment frag. The first frag starting
> from align_frag that has rs_align_code is the alignment frag.
Here is the new patch.
H.J.
-------------- next part --------------
2004-03-02 H.J. Lu <hongjiu.lu@intel.com>
* config/tc-ia64.c (align_frag): New.
(md_assemble): Set the tc_frag_data field in align_frag for
IA64_OPCODE_FIRST instructions.
(ia64_md_do_align): Set align_frag.
(ia64_handle_align): Add a stop bit if needed.
* config/tc-ia64.h (TC_FRAG_TYPE): New.
(TC_FRAG_INIT): New.
--- gas/config/tc-ia64.c.alloc 2004-02-24 09:32:19.000000000 -0800
+++ gas/config/tc-ia64.c 2004-03-02 18:52:25.000000000 -0800
@@ -636,6 +636,9 @@ static struct gr {
valueT value;
} gr_values[128] = {{ 1, 0, 0 }};
+/* Remember the alignment frag. */
+static fragS *align_frag;
+
/* These are the routines required to output the various types of
unwind records. */
@@ -9990,7 +9993,24 @@ md_assemble (str)
flags = idesc->flags;
if ((flags & IA64_OPCODE_FIRST) != 0)
- insn_group_break (1, 0, 0);
+ {
+ /* The alignment frag has to end with a stop bit only if the
+ next instruction after the alignment directive has to be
+ the first instruction in an instruction group. */
+ if (align_frag)
+ {
+ while (align_frag->fr_type != rs_align_code)
+ {
+ align_frag = align_frag->fr_next;
+ assert (align_frag);
+ }
+ if (align_frag->fr_next == frag_now)
+ align_frag->tc_frag_data = 1;
+ }
+
+ insn_group_break (1, 0, 0);
+ }
+ align_frag = NULL;
if ((flags & IA64_OPCODE_NO_PRED) != 0 && qp_regno != 0)
{
@@ -10808,6 +10828,8 @@ ia64_md_do_align (n, fill, len, max)
int len ATTRIBUTE_UNUSED;
int max ATTRIBUTE_UNUSED;
{
+ /* The current frag is an alignment frag. */
+ align_frag = frag_now;
if (subseg_text_p (now_seg))
ia64_flush_insns ();
}
@@ -10823,13 +10845,20 @@ ia64_handle_align (fragp)
static const unsigned char le_nop[]
= { 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00};
+ static const unsigned char le_nop_stop[]
+ = { 0x0d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00};
int bytes;
char *p;
+ const unsigned char *nop;
if (fragp->fr_type != rs_align_code)
return;
+ /* Check if this frag has to end with a stop bit. */
+ nop = fragp->tc_frag_data ? le_nop_stop : le_nop;
+
bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
p = fragp->fr_literal + fragp->fr_fix;
@@ -10845,7 +10874,7 @@ ia64_handle_align (fragp)
}
/* Instruction bundles are always little-endian. */
- memcpy (p, le_nop, 16);
+ memcpy (p, nop, 16);
fragp->fr_var = 16;
}
--- gas/config/tc-ia64.h.alloc 2004-03-01 09:05:22.000000000 -0800
+++ gas/config/tc-ia64.h 2004-03-02 12:11:27.000000000 -0800
@@ -159,6 +159,10 @@ extern void ia64_convert_frag (fragS *);
#define TC_DWARF2_EMIT_OFFSET ia64_dwarf2_emit_offset
#define tc_check_label(l) ia64_check_label (l)
+/* Record if an alignment frag should end with a stop bit. */
+#define TC_FRAG_TYPE int
+#define TC_FRAG_INIT(FRAGP) do {(FRAGP)->tc_frag_data = 0;}while (0)
+
#define MAX_MEM_FOR_RS_ALIGN_CODE (15 + 16)
#define WORKING_DOT_WORD /* don't do broken word processing for now */
More information about the Binutils
mailing list